I'm exploring the 'hackneyed' example of length-indexed vectors, code adapted from Richard Eisenberg's thesis section 3.1
{-# LANGUAGE GADTs, TypeFamilies, DataKinds, KindSignatures,
TypeOperators, ScopedTypeVariables #-}
-- PatternSignatures -- deprecated
import GHC.Types (Type)
data Nat = Zero | Succ Nat
data Vec :: Type -> Nat -> Type where
Nil :: Vec a Zero -- E has 'Zero
(:>) :: a -> Vec a n -> Vec a (Succ n) -- E has 'Succ
infixr 5 :>
type family (+) (n :: Nat) (m :: Nat) :: Nat where
(+) Zero m = m
(+) (Succ n') m = Succ (n' + m)
append :: Vec a n -> Vec a m -> Vec a (n + m)
append (Nil :: Vec aa Zero) (w :: Vec aa mm) = w :: Vec aa (Zero + mm)
append (x :> (v :: Vec a n')) (w :: Vec a m) = x :> ((append v w) :: Vec a (n' + m))
The append Nil ...
equation is rejected (GHC 8.6.5)
* Couldn't match type `m' with `n + m'
`m' is a rigid type variable bound by
the type signature for:
append :: forall a (n :: Nat) (m :: Nat).
Vec a n -> Vec a m -> Vec a (n + m)
at ...
Expected type: Vec a (n + m)
Actual type: Vec a ('Zero + m)
Giving the result type as :: Vec aa mm
is also rejected.
Expected type: Vec a (n + m)
Actual type: Vec a m
weird because that's accepted (see below).
What I'm really trying to do is use PatternSignatures
for the arguments to append
. But that extension is deprecated, I have to use ScopedTypeVariables
. And that means the tyvars from the signature for append
are in scope in the equations. So I've used fresh tyvar names.
The GADT gives Nil :: Vec a Zero
, so I give that as its pattern signature (with a fresh aa
). But it seems GHC can't unify the n
from append
's signature with the Zero
. If I change that equation to either of these, all is happy:
append (Nil :: Vec aa nn) (w :: Vec aa mm) = w :: Vec aa (nn + mm)
append (Nil :: Vec aa nn) (w :: Vec aa mm) = w :: Vec aa (mm)
To validate those, GHC must be figuring out that Nil :: Vec a Zero
and that Zero + m = m
from the type family equation for +
. So why is it grumpy about the pattern signature with Zero
?
(I was originally trying to give the equations for append
purely with PatternSignatures
, to see if GHC could infer the signature. That didn't get off the ground.)