I want to develop a type safe lookup function for the following data type:
data Attr (xs :: [(Symbol,*)]) where
Nil :: Attr '[]
(:*) :: KnownSymbol s => (Proxy s, t) -> Attr xs -> Attr ('(s , t) ': xs)
The obvious lookup function would be like:
lookupAttr :: (KnownSymbol s, Lookup s env ~ 'Just t) => Proxy s -> Attr env -> t
lookupAttr s ((s',t) :* env')
= case sameSymbol s s' of
Just Refl -> t
Nothing -> lookupAttr s env'
where Lookup
type family is defined in singletons library. This definition fails to type check on GHC 7.10.3 with the following error message:
Could not deduce (Lookup s xs ~ 'Just t)
from the context (KnownSymbol s, Lookup s env ~ 'Just t)
bound by the type signature for
lookupAttr :: (KnownSymbol s, Lookup s env ~ 'Just t) =>
Proxy s -> Attr env -> t
This message is generated for the recursive call lookupAttr s env'
. This is reasonable, since we have that if
Lookup s ('(s',t') ': env) ~ 'Just t
holds, and
s :~: s'
isn't provable, then
Lookup s env ~ 'Just t
must hold. My question is, how can I convince Haskell type checker that this is indeed true?
sameSymbol
defined? Is that from the singletons library as well? – KwarrtzSymbol
's rather janky implementation in GHC. If you're building a type-safe embedded DSL I think you should seriously consider HOAS as a simpler alternative. – Benjamin Hodgson