¿Puede Template Haskell descubrir los nombres y / o las declaraciones de los sinónimos de tipo asociados declarados en una clase de tipo? Esperaba reify
hacer lo que quisiera, pero no parece proporcionar toda la información necesaria. Funciona para obtener firmas de tipo de función:
% 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)))])
[]
Sin embargo, agregar un sinónimo de tipo asociado a la clase no causa ningún cambio (hasta el cambio de nombre) en la salida:
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 sé el nombre de F
, puedo buscar información al respecto:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Pero no puedo encontrar el nombre de F
en primer lugar. Incluso si agrego una instancia de la clase de tipo, InstanceD
no tiene ninguna información sobre la definición:
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
no funciona, ¿hay alguna solución alternativa, aparte de enumerar los sinónimos de tipo asociado manualmente?
Este problema está presente en GHC 7.8.3 con la versión 2.9.0.0 del paquete template-haskell; también estuvo presente en GHC 7.4.2 con la versión 2.7.0.0 del paquete template-haskell. (No verifiqué en GHC 7.6. *, Pero imagino que también estuvo presente allí.) Estoy interesado en soluciones para cualquier versión de GHC (incluyendo "esto solo se solucionó en la versión V de GHC ").
InstanceD
s que vi con reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
evalúa a [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, que carece de las instancias de tipo de familia.
reify
no devuelva la información necesaria. ¿Quizás show
está ocultando parte de la información? ¿Has intentado examinar el Info
objeto directamente?
Info
la Show
instancia es solo la derivada, e igual para la Show
instancia de Dec
. Sin embargo, también puedo verificar directamente, como usted pidió, y no: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produce just a SigD
- ¡eso es realmente lo único [Dec]
en el ClassD
! (requiere LambdaCase
) Estoy de acuerdo en que es extraño; por eso hice esta pregunta :-)
reifyInstances
?