> Is `type F[_]` not a higher kinded type?
type F[X] = … // has kind '* -> *'
type F[_] = … // also has kind '* -> *'
Both are really the same thing.
(Be cautious with the term 'higher-kinded'. A simple kind like '* -> *'
doesn't qualify as 'higher', unless you say that a function of type 'T
=> T' is a higher order function.)
> Why does `type F[_] = Int` compile whereas `type F[_] = List` does
> not?
The syntax `type F[X] = …` declares a type alias. After the `=`, a
regular type is expected. `List` is not a type by itself.
When trying to figure out what is allowed after `type F[_] = `, it's the
same. Just a regular type.
> On the other hand with `trait HKT[F[_]]` it's the different way.
> `type X = HKT[Int]` does not compile whereas `type X = HKT[List]`
> does. What is the difference?
Now, `F[_]` is a type parameter. The `[_]` indicates that `F` must be a
type constructor of kind `* -> *`. `List` is such a type constructor,
`Int` is not.
(The trait `HKT` can be said to be higher-kinded, since it's kind is (*
-> *) -> *.)
Let me try to elaborate. Assume you want to refactor this:
trait HKT[F[_]]
to using type members.
trait HKT {
type F[_]
}
Extending the former:
class Unicorn extends HKT[Option]
Extending the latter:
class Unicorn extends HKT {
type F[X] = Option[X] // observe that `X` appears twice
}
(I do understand that the difference is very subtle. Feel free to ask
further questions.)
> `const0("")` compiles fine and has type `const0.Out[String]` but is a
> type alias for Int. Are there use cases, in which one can take use of
> the parameterization to String?
I don't understand the question.
> FlyingDog is a functor, right?
Right.
> With a type lambda, how does the implementation of `swoosh` look when
> there is no type parameter that can be applied to `f` or is it
> impossible to use such a type [...]
>
> class X
> new FlyingDog[({type λ[α] = X})#λ]{ def swoosh[A,B](f: A =>
> B, a: X): X = ??? }
No, it's possible.
You already simplified the types. Indeed, the functor for the constant
type `X` is trivial:
scala> trait Z
defined trait Z
scala> new FlyingDog[({ type λ[α] = Z })#λ] {
def swoosh[A,B](f: A => B, a: Z): Z = a
}
res14: java.lang.Object with FlyingDog[[_]Z] = $anon$1@24ebb33
> (is this what you meant with
> "[...]except that there's no real use case")?
No. The construct `class A[_]` has no use case for the following reasons:
1) type lambdas exists
2) A[T₁] and A[T₂] are treated as completely disparate types, although
they're "morally" equivalent:
scala> implicitly[A[Int] =:= A[String]]
<console>:9: error: Cannot prove that A[Int] =:= A[String].
Contrast that with:
scala> type λ[_] = A
defined type alias λ
scala> implicitly[λ[Int] =:= λ[String]]
res16: =:=[λ[Int],λ[String]] = <function1>