Czy szablon Haskell może znaleźć nazwy i / lub deklaracje powiązanych synonimów typów zadeklarowanych w klasie typu? Spodziewałem się, reify
że zrobię to, co chcę, ale wydaje się, że nie zawiera wszystkich niezbędnych informacji. Działa w celu uzyskania podpisów typów funkcji:
% ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
...
Prelude> -- I'll be inserting line breaks and whitespace for clarity
Prelude> -- in all GHCi output.
Prelude> :set -XTemplateHaskell
Prelude> import Language.Haskell.TH
Prelude Language.Haskell.TH> class C a where f :: a -> Int
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C)
ClassI (ClassD [] Ghci1.C [PlainTV a_1627398388] []
[SigD Ghci1.f
(ForallT [PlainTV a_1627398388]
[ClassP Ghci1.C [VarT a_1627398388]]
(AppT (AppT ArrowT (VarT a_1627398388))
(ConT GHC.Types.Int)))])
[]
Jednak dodanie do klasy synonimu powiązanego nie powoduje żadnych zmian (aż do zmiany nazwy) w danych wyjściowych:
Prelude Language.Haskell.TH> :set -XTypeFamilies
Prelude Language.Haskell.TH> class C' a where type F a :: * ; f' :: a -> Int
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
[SigD Ghci3.f'
(ForallT [PlainTV a_1627405973]
[ClassP Ghci3.C' [VarT a_1627405973]]
(AppT (AppT ArrowT (VarT a_1627405973))
(ConT GHC.Types.Int)))])
[]
Jeśli znam nazwę F
, mogę wyszukać informacje na jej temat:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Ale nie mogę znaleźć nazwy F
. Nawet jeśli dodam instancję klasy typu, InstanceD
nie zawiera ona żadnych informacji o definicji:
Prelude Language.Haskell.TH> instance C' [a] where type F [a] = a ; f' = length
Prelude Language.Haskell.TH> f' "Haskell"
7
Prelude Language.Haskell.TH> 42 :: F [Integer]
42
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
[SigD Ghci3.f'
(ForallT [PlainTV a_1627405973]
[ClassP Ghci3.C' [VarT a_1627405973]]
(AppT (AppT ArrowT (VarT a_1627405973))
(ConT GHC.Types.Int)))])
[InstanceD []
(AppT (ConT Ghci3.C')
(AppT ListT (VarT a_1627406161)))
[]]
Jeśli reify
nie zadziała, czy istnieje inne obejście niż ręczne wyświetlanie synonimów typu stowarzyszonego?
Ten problem występuje w GHC 7.8.3 w wersji 2.9.0.0 pakietu template-haskell; był także obecny w GHC 7.4.2 z wersją 2.7.0.0 pakietu szablon-haskell. (Nie sprawdziłem GHC 7.6. *, Ale wyobrażam sobie, że tam też był obecny.) Interesują mnie rozwiązania dla dowolnej wersji GHC (w tym „naprawiono to tylko w wersji V GHC ”).
InstanceD
jak widziałem z reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
ewaluuje do [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, w którym brakuje instancji rodziny typów.
reify
nie zwraca niezbędnych informacji. Być może show
ukrywasz niektóre informacje? Czy próbowałeś Info
bezpośrednio zbadać obiekt?
Info
jest Show
wystąpienie jest tylko pochodzi jeden i ten sam dla Show
przykładu do Dec
. Jednakże, mogę też sprawdzić bezpośrednio, jak prosiłeś, a nie: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produkuje just a SigD
- to naprawdę jedyna rzecz na [Dec]
w ClassD
! (wymaga LambdaCase
). Zgadzam się, że to dziwne; dlatego zadałem to pytanie :-)
reifyInstances
?