Data.Foldable shows the following algebraic data type:
data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)
Its kind is * -> *. It requires an a type.
Prelude> :k Tree
Tree :: * -> *
Let's look now at trait Foldable[_], a "higher-kinded type" from Scala from Functional Programming in Scala:
trait Foldable[F[_]] {
def foldRight[A,B](as: F[A])(z: B)(f: (A,B) => B): B
...
}
The excellent book says:
Just like values and functions have types, types and type constructors have kinds. Scala uses kinds to track how many type arguments a type constructor takes, ...
EDIT
When specifying trait Foldable[F[_]], does the F[_] always indicate a higher-kinded type? Is it possible for F[_] to be anything else? Could it be a type - F[A]?
A higher kinded type is a concept that reifies a type constructor as an actual type. A type constructor can be thought of in these analogies: like a function in the type universe. as a type with a "hole" in it.
Higher-kinded types are useful when we want to create a container that can hold any type of items; we don't need a different type for each specific content type.
The most-used example of higher-kinded type polymorphism in Haskell is the Monad interface.
HKTs are a powerful abstraction. Just as there are different types of higher-order functions, so are there so-called 'higher-kinded types'.
The F[_] in Scala stands for something like * -> * in Haskell: that is a type which "receives" a concrete type (the _ in Scala and the first * in Haskell) and returns a new concrete type (F[A] for some concrete type A and concrete "container" F in Scala).
So yes, F[_] stands for some higher kinded type like List[_] or Option[_]. It wouldn't be useful to define traversable in scala like trait Foldable[A,F[A]] because we would be saying that Foldable needs to be defined with the specific thing being folded (the A).
You haven't asked much of a question, but if you want a general idea: yes, the "kind" system of both of these languages is a type system for their own type system. The * type is not a wildcard but a special type atom; * is the type of "concrete types" like String, [String], and Tree String.
In turn there are things like [] or Tree (see the difference?) which have kind * -> *; this is the type of "singly-parametrized types" which take a concrete type and produce another concrete type.
A last example: there are things called "monad transformers" like MaybeT which takes a monad like IO and produces another monad like IO . Maybe (if you will pardon the use of function composition operators where they're not generally admitted). What kind does that have? Why, (* -> *) -> * -> * of course: monads have kind * -> * so we take one of those types and transform it into another of those types.
I cannot speak with so much expertise on Scala syntax, but on the Internet we see a definition of a monad transformer trait in Scala as:
trait MonadTrans[F[_[_], _]] {
def lift[G[_] : Monad, A](a: G[A]): F[G, A]
}
so I think your guess is mostly right (that the brackets indicate a dependent type).
Having a type theory of these things guarantees that you never write things like IO IO as a concrete type, or MaybeT String.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With