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