|
| 1 | +--- |
| 2 | +layout: doc-page |
| 3 | +title: "Kind Polymorphism" |
| 4 | +--- |
| 5 | + |
| 6 | +Normally type parameters in Scala are partitioned into _kinds_. First-level types are types of values. Higher-kinded types are type constructurs |
| 7 | +such as `List` or `Map`. The kind of a type is indicated by the top type of which it is a subtype. Normal types are subtypes of `Any`, |
| 8 | +covariant single argument type constructors such as `List` are subtypes of `[+X] => Any`, and the `Map` type constructor is |
| 9 | +a subtype of `[X, +Y] => Any`. |
| 10 | + |
| 11 | +A type can be used only as prescribed by its kind. Subtypes of `Any` cannot be applied to type arguments whereas subtypes of `[X] => Any` |
| 12 | +_must_ be applied to a type argument, unless they are passed to type parameters of the same kind. |
| 13 | + |
| 14 | +Sometimes we would like to have type parameters that can have more than one kind, for instance to define an implicit |
| 15 | +value that works for parameters of any kind. This is now possible through a form of (_subtype_) kind polymorphism. |
| 16 | +Kind polymorphism relies on the special type `scala.AnyKind` that can be used as an upper bound of a type. |
| 17 | + |
| 18 | +```scala |
| 19 | +def f[T <: AnyKind] = ... |
| 20 | +``` |
| 21 | + |
| 22 | +The actual type arguments of `f` can then be types of arbitrary kinds. So the following would all be legal: |
| 23 | + |
| 24 | +```scala |
| 25 | +f[Int] |
| 26 | +f[List] |
| 27 | +f[Map] |
| 28 | +f[[X] => String] |
| 29 | +``` |
| 30 | + |
| 31 | +We call type parameters and abstract types with an `AnyKind` upper bound _any-kinded types_`. |
| 32 | +Since the actual kind of an any-kinded type is unknown, its usage must be heavily restricted: An any-kinded type |
| 33 | +can be neither the type of a value, nor can it be instantiated with type parameters. So about the only |
| 34 | +thing one can do with an any-kinded type is to pass it to another any-kinded type argument. |
| 35 | +Nevertheless, this is enough to achieve some interesting generalizations that work across kinds, typicially |
| 36 | +through advanced uses of implicits. |
| 37 | + |
| 38 | +(todo: insert good concise example) |
| 39 | + |
| 40 | +Some technical details: `AnyKind` is a synthesized class just like `Any`, but without any members. It extends no other class. |
| 41 | +It is declared `abstract` and `final`, so it can be neither instantiated nor extended. |
| 42 | + |
| 43 | +`AnyKind` plays a special role in Scala's subtype system: It is a supertype of all other types no matter what their kind is. It is also assumed to be kind-compatible with all other types. Furthermore, `AnyKind` is treated as a higher-kinded type (so it cannot be used as a type of values), but at the same time it has no type parameters (so it cannot be instantiated). |
0 commit comments