Template Haskell può scoprire i nomi e / o le dichiarazioni dei sinonimi di tipo associati dichiarati in una classe di tipo? Mi aspettavo che reify
avrebbe fatto quello che volevo, ma non sembra fornire tutte le informazioni necessarie. Funziona per ottenere le firme dei tipi di funzione:
% 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)))])
[]
Tuttavia, l'aggiunta di un sinonimo di tipo associato alla classe non provoca alcuna modifica (fino alla ridenominazione) nell'output:
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 conosco il nome di F
, posso cercare informazioni al riguardo:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Ma non riesco a trovare il nome F
in primo luogo. Anche se aggiungo un'istanza della classe type, InstanceD
non contiene alcuna informazione sulla definizione:
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
non funziona, esiste una soluzione alternativa, oltre a elencare manualmente i sinonimi del tipo associato?
Questo problema è presente in GHC 7.8.3 con la versione 2.9.0.0 del pacchetto template-haskell; era presente anche in GHC 7.4.2 con la versione 2.7.0.0 del pacchetto template-haskell. (Non ho controllato GHC 7.6. *, Ma immagino che fosse presente anche lì.) Sono interessato a soluzioni per qualsiasi versione di GHC (incluso "questo è stato risolto solo nella versione V di GHC ").
InstanceD
che ho visto con reify
: putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
valuta [InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, a cui mancano le istanze della famiglia di tipi.
reify
non restituisca le informazioni necessarie. Forse show
nasconde alcune delle informazioni? Hai provato a esaminare l' Info
oggetto direttamente?
Info
l' Show
istanza sia solo quella derivata, e lo stesso per l' Show
istanza di Dec
. Tuttavia, posso anche verificare direttamente, come lei ha chiesto, e non: putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produce just a SigD
- che è in realtà l'unica cosa che nel [Dec]
nel ClassD
! (richiede LambdaCase
). Sono d'accordo è strano; ecco perché ho posto questa domanda :-)
reifyInstances
?