Chcę rozwijać funkcję typu bezpieczny odnośników dla następującego typu danych:Rodzaj bezpieczne wyszukiwanie na heterogenicznych list w Haskell
data Attr (xs :: [(Symbol,*)]) where
Nil :: Attr '[]
(:*) :: KnownSymbol s => (Proxy s, t) -> Attr xs -> Attr ('(s , t) ': xs)
Funkcja Lookup oczywiste byłoby jak:
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'
gdzie Lookup
rodzina typów jest zdefiniowana w bibliotece singletons. Definicja ta nie typ kontroli na GHC 7.10.3 z następującym komunikatem o błędzie:
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
Ten komunikat jest generowany dla rekurencyjnego wywołania lookupAttr s env'
. Jest to uzasadnione, ponieważ mamy, że jeśli
Lookup s ('(s',t') ': env) ~ 'Just t
trzyma i
s :~: s'
nie jest do udowodnienia, a następnie
Lookup s env ~ 'Just t
musi posiadać. Moje pytanie brzmi: jak mogę przekonać sprawdzacz typu Haskella, że to prawda?
Gdzie zdefiniowano "ten samSymbol"? Czy to samo dotyczy biblioteki singletons? – Kwarrtz
Och, nieważne. Znalazłem go w [GHC.TypeLits] (https://hackage.haskell.org/package/base-4.8.2.0/docs/GHC-TypeLits.html). – Kwarrtz
Używając łańcuchów do reprezentowania powiązanych zmiennych, płacisz znaczną cenę w złożoności implementacji języka. Unikanie przechwytywania i alfa-równoważność są notorycznie trudne do uzyskania, nie wspominając o kosztach walki z dość symboliczną implementacją "Symbol" w GHC. Jeśli budujesz bezpieczny DSL typu, myślę, że powinieneś poważnie rozważyć [HOAS] (https://en.wikipedia.org/wiki/Higher-order_abstract_syntax) jako prostszą alternatywę. –