Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Higher Kinded Types in Scala and Haskell

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]?

like image 581
Kevin Meredith Avatar asked Jan 09 '15 18:01

Kevin Meredith


People also ask

What are higher Kinded types Haskell?

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.

Why are there high Kinded types?

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.

Is Monad a higher Kinded type?

The most-used example of higher-kinded type polymorphism in Haskell is the Monad interface.

Does typescript have higher Kinded types?

HKTs are a powerful abstraction. Just as there are different types of higher-order functions, so are there so-called 'higher-kinded types'.


2 Answers

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).

like image 129
miguel Avatar answered Sep 27 '22 18:09

miguel


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.

like image 45
CR Drost Avatar answered Sep 27 '22 18:09

CR Drost