GHC has type level literal Nats. I can read a few things about them, for instance, here:
https://ghc.haskell.org/trac/ghc/wiki/TypeNats
Unfortunately, there seems to be little documentation about them, and almost nothing I try to do with them actually works.
Comment 18 from this page mentions this simple example of size parametrized Vecs (I've added LANGUAGE pragmas and an import statement):
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Vec :: Nat -> * -> * where
Nil :: Vec 0 a
(:>) :: a -> Vec n a -> Vec (n+1) a
(+++) :: Vec n a -> Vec m a -> Vec (n+m) a
Nil +++ bs = bs
(a :> as) +++ bs = a :> (as +++ bs)
It wasn't working at the time, but then the implementation was supposedly modified so that this worked. That was 5 years ago... but it doesn't work on my GHC 7.10.1:
trash.hs:15:20:
Could not deduce ((n + m) ~ ((n1 + m) + 1))
from the context (n ~ (n1 + 1))
bound by a pattern with constructor
:> :: forall a (n :: Nat). a -> Vec n a -> Vec (n + 1) a,
in an equation for ‘+++’
at trash.hs:15:2-8
NB: ‘+’ is a type function, and may not be injective
Expected type: Vec (n + m) a
Actual type: Vec ((n1 + m) + 1) a
Relevant bindings include
bs :: Vec m a (bound at trash.hs:15:15)
as :: Vec n1 a (bound at trash.hs:15:7)
(+++) :: Vec n a -> Vec m a -> Vec (n + m) a
(bound at trash.hs:14:1)
In the expression: a :> (as +++ bs)
In an equation for ‘+++’: (a :> as) +++ bs = a :> (as +++ bs)
What's the deal here? Are type level literal Nats supposed to be usable for this kind of thing? If so, how do I implement the (+++) function? If not, what is their use case?
GHC.TypeLits
is, sticked to a manually-defined Peano type, with a codata-style type class to take recursion schemes etc. to aNat
-qualified level, instead of explicitly solving any number equalities. – leftaroundabout