Template Haskell peut-il connaître les noms et / ou les déclarations des synonymes de type associés déclarés dans une classe de type? Je m'attendais à reify
ce que je fasse ce que je veux, mais cela ne semble pas fournir toutes les informations nécessaires. Cela fonctionne pour obtenir des signatures de type de fonction:
% 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)))])
[]
Cependant, l'ajout d'un synonyme de type associé à la classe n'entraîne aucun changement (jusqu'à renommer) dans la sortie:
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)))])
[]
Si je connais le nom de F
, je peux rechercher des informations à ce sujet:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Mais je ne trouve pas le nom de F
en premier lieu. Même si j'ajoute une instance de la classe type, le InstanceD
n'a aucune information sur la définition:
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)))
[]]
Si reify
cela ne fonctionne pas, existe-t-il une solution de contournement, autre que la liste manuelle des synonymes de type associé?
Ce problème est présent dans GHC 7.8.3 avec la version 2.9.0.0 du package template-haskell; il était également présent dans GHC 7.4.2 avec la version 2.7.0.0 du package template-haskell. (Je n'ai pas vérifié GHC 7.6. *, Mais j'imagine qu'il y était aussi.) Je suis intéressé par des solutions pour n'importe quelle version de GHC (y compris "cela n'a été corrigé que dans GHC version V ").
InstanceD
s que j'ai vu avec reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
évalue à [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, auquel il manque les instances de famille de types.
reify
cela ne renvoie pas les informations nécessaires. Peut show
- être cache-t-il certaines informations? Avez-vous essayé d'examiner Info
directement l' objet?
Info
l' Show
instance ne soit que dérivée, et même pour l' Show
instance de Dec
. Cependant, je peux aussi vérifier directement, comme vous l'avez demandé, et non: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produit just a SigD
- c'est vraiment la seule chose [Dec]
dans le ClassD
! (nécessite LambdaCase
). Je suis d'accord, c'est bizarre; c'est pourquoi j'ai posé cette question :-)
reifyInstances
?