Kann Template Haskell die Namen und / oder Deklarationen der zugehörigen Typensynonyme herausfinden, die in einer Typklasse deklariert sind? Ich hatte erwartet, reify
dass ich tun würde, was ich will, aber es scheint nicht alle notwendigen Informationen zu liefern. Es funktioniert zum Abrufen von Funktionstypsignaturen:
% 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)))])
[]
Das Hinzufügen eines zugeordneten Typensynonyms zur Klasse bewirkt jedoch keine Änderung (bis zum Umbenennen) der Ausgabe:
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)))])
[]
Wenn ich den Namen von kenne F
, kann ich Informationen darüber nachschlagen:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
Aber ich kann den Namen überhaupt nicht finden F
. Selbst wenn ich eine Instanz der Typklasse hinzufüge, enthält die InstanceD
keine Informationen zur Definition:
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)))
[]]
Wenn dies reify
nicht funktioniert, gibt es eine andere Problemumgehung als die manuelle Auflistung der Synonyme für den assoziierten Typ?
Dieses Problem tritt in GHC 7.8.3 mit Version 2.9.0.0 des Template-Haskell-Pakets auf. Es war auch in GHC 7.4.2 mit Version 2.7.0.0 des Template-Haskell-Pakets vorhanden. (Ich habe GHC 7.6 nicht überprüft. *, Aber ich kann mir vorstellen, dass es auch dort vorhanden war.) Ich bin an Lösungen für jede Version von GHC interessiert (einschließlich "Dies wurde nur in GHC Version V behoben ").
quelle
reifyInstances
?InstanceD
s, wie ich sie gesehen habereify
:putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])
evaluiert zu[InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []]
, was den Instanzen der Typfamilie fehlt.reify
nicht die notwendigen Informationen zurückgegeben werden. Vielleichtshow
versteckt sich ein Teil der Informationen? Haben Sie versucht, dasInfo
Objekt direkt zu untersuchen?Info
, dieShow
Instanz ist nur die abgeleitete und die gleiche für dieShow
Instanz fürDec
. Ich kann aber auch direkt nachsehen, wie Sie gefragt haben, und nein:putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")
produziertjust a SigD
- das ist wirklich das einzige, was[Dec]
in derClassD
! (erfordertLambdaCase
). Ich bin damit einverstanden, dass es seltsam ist; Deshalb habe ich diese Frage gestellt :-)Antworten:
Es ist nicht implementiert, weil niemand es angefordert hat.
Das Seltsame ist, dass TH einen eigenen AST verwendet, der nicht dem AST des internen Compilers folgt. Infolgedessen ist eine neue Funktion (z. B. zugehörige Typenfamilien) nicht automatisch über TH verfügbar. Jemand muss ein Ticket öffnen und implementieren.
Als Referenz: Die interne
reifyClass
Funktion ignoriert zugehörige Typfamilien (dies ist das 5. Element des von zurückgegebenen TupelsclassExtraBigSig
, siehe auch Definition vonClassATItem
.)Technisch sollte es einfach sein, die Unterstützung für zugeordnete Typfamilien in zu implementieren
reify
, aber höchstwahrscheinlich sind abwärtsinkompatible Änderungen in der TH-API erforderlich, z. B. weil der AST die zugehörigen Typstandards nicht zu unterstützen scheint.Hinzugefügt: Es ist jetzt implementiert (übrigens ohne API-Änderung) und wird wahrscheinlich in der nächsten
ghc
Version verfügbar sein .quelle
FamilyD
die zugehörigen Standardeinstellungen für Typensynonyme nicht unterstützt werden . Sie verwenden sie wahrscheinlich nicht, aber für die vollständige Lösung ist möglicherweise eine API-Änderung erforderlich.