{-# language GADTs, KindSignatures, DataKinds, TypeApplications, TypeOperators,
TypeFamilies, PolyKinds, UndecidableInstances, RankNTypes, AllowAmbiguousTypes #-}
import GHC.TypeLits
I would like to index a type-level list with a type-level Nat:
type family Index (xs :: [a]) (k :: Nat) where
Index (x:xs) 0 = x
Index (x:xs) k = Index xs (k - 1)
Note that I'm using GHC.TypeLits.Nat instead of, say, data Nat = Z | S Nat, as the actual parameter comes from an SNat and I would like to avoid storing numbers in unary at runtime.
This definition works fine for concrete types:
*Main> :k! Index [Int, Double, String] 1
Index [Int, Double, String] 1 :: *
= Double
However, in some of my functions, I need to prove that Index v n ~ Index (a:v) (n+1). GHC cannot solve this by itself:
prf :: Index v n -> Index (a:v) (n + 1)
prf x = x
• Couldn't match expected type ‘Index (a : v) (n + 1)’
with actual type ‘Index v n’
NB: ‘Index’ is a non-injective type family
• In the expression: x
In an equation for ‘prf’: prf x = x
• Relevant bindings include
x :: Index v n (bound at Minimal.hs:11:5)
prf :: Index v n -> Index (a : v) (n + 1)
(bound at Minimal.hs:11:1)
Is it possible to prove this type equality? If not, what are my alternatives?