O Template Haskell pode descobrir os nomes e / ou as declarações dos sinônimos de tipo associados declarados em uma classe de tipo? Eu esperava reify
que fizesse o que eu quero, mas parece não fornecer todas as informações necessárias. Ele funciona para obter assinaturas de tipo de função:
% 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)))])
[]
No entanto, adicionar um sinônimo de tipo associado à classe não causa alterações (até renomear) na saída:
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)))])
[]
Se eu souber o nome F
, posso procurar informações sobre ele:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Mas não consigo encontrar o nome de F
em primeiro lugar. Mesmo se eu adicionar uma instância da classe type, InstanceD
ela não possui nenhuma informação sobre a definição:
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)))
[]]
Se reify
não funcionar, existe uma solução alternativa, além de listar os sinônimos do tipo de associado manualmente?
Esse problema está presente no GHC 7.8.3 com a versão 2.9.0.0 do pacote template-haskell; também estava presente no GHC 7.4.2 com a versão 2.7.0.0 do pacote template-haskell. (Eu não verifiquei o GHC 7.6. *, Mas imagino que ele estivesse presente também.) Estou interessado em soluções para qualquer versão do GHC (incluindo "isso foi corrigido apenas na versão V do GHC ").
InstanceD
s que vi com reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
avalia para [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, o que não possui as instâncias de família de tipo.
reify
não retorne as informações necessárias. Talvez show
esteja escondendo algumas informações? Você já tentou examinar o Info
objeto diretamente?
Info
a Show
instância seja apenas a derivada e a mesma para a Show
instância Dec
. No entanto, também posso verificar diretamente, como você pediu, e não: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produz just a SigD
- essa é realmente a única coisa no [Dec]
in ClassD
! (requer LambdaCase
). Eu concordo que é estranho; é por isso que eu fiz esta pergunta :-)
reifyInstances
?