Reputation: 41919
Maybe
, which I understand to be a type constructor
, has kind * -> *
. As I understand, it needs a type in order to produce a type.
ghci> :k Maybe
Maybe :: * -> *
ghci> :k Maybe Int
Maybe Int :: *
However, what does the following output mean?
ghci> :k Random
Random :: * -> Constraint
Upvotes: 2
Views: 80
Reputation: 54068
There are a handful of kinds in Haskell. A concrete type has kind *
, this means that it is fully applied, so types like Int
, [String]
, IO (Maybe Int)
. Then there are kinds that take the form * -> k
, where k
is a kind variable. These are just like functions in Haskell that take 1 or more arguments, except *
has to be a concrete type, it isn't variable. Examples would be
> :kind Maybe
Maybe :: * -> *
> :kind Either
Either :: * -> * -> *
> data Foo a b c d e = Foo
> :kind Foo
Foo :: * -> * -> * -> * -> * -> *
Then there is the kind Constraint
, which is constructed with one or more1 other kinds:
> :kind Num
Num :: * -> Constraint
> :kind Show
Show :: * -> Constraint
> import Control.Monad.State
> :kind MonadState
MonadState :: * -> (* -> *) -> Constriant
The last one is a bit more complex, but think of it like a higher order function, where (* -> *)
means that the second argument must be a type constructor that has one type argument left.
Random
is just a simple typeclass, so it takes a fully applied type and produces a Constraint
.
There is also the primitive kind #
, values of types that are primitive and baked in to GHC, they even require a language extension just to parse their names:
> import GHC.Prim
> :set -XMagicHash
> :i Int#
data Int#
> :k Int#
Int# :: #
Most Haskell programmers won't ever need to use these, but they're available if you need to do low level programming for the GHC API.
With a couple extensions, you can even make kinds yourself
> :set -XDataKinds
> :set -XKindSignatures
> :set -XGADTs
> -- Multiline input in GHCi
> :set +m
> data FlagType = Flag1 | Flag2 deriving (Show)
> data Foo :: FlagType -> * -> *
| F1 :: Int -> Foo 'Flag1 Int
| F2 :: String -> Foo 'Flag2 String
|
> :t F1 1
F1 1 :: Foo 'Flag1 Int
> :t F2 "foo"
F2 "foo" :: Foo 'Flag2 String
Kinds give us a form of type level programming, there are lots of tricks that can be done with them to build nice APIs.
Upvotes: 7