259 votes

Obtention de synonymes de types associés avec le modèle Haskell

Template Haskell peut-il trouver les noms et/ou les déclarations des synonymes de type associés déclarés dans une classe de type ? J'attendais reify ferait ce que je veux, mais il ne semble pas fournir toutes les informations nécessaires. Il fonctionne pour obtenir les 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 ne provoque aucun changement (jusqu'au renommage) 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 chercher 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 n'arrive pas à trouver le nom de F en premier lieu. Même si j'ajoute une instance de la classe de type, l'élément InstanceD ne dispose d'aucune des informations relatives à 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 ne fonctionne pas. Existe-t-il une solution de rechange, autre que de lister manuellement les synonymes du type d'associé ?

Ce problème est présent dans GHC 7.8.3 avec la version 2.9.0.0 du paquetage template-haskell ; il était également présent dans GHC 7.4.2 avec la version 2.7.0.0 du paquetage template-haskell. (Je n'ai pas vérifié dans GHC 7.6.*, mais j'imagine qu'il y était aussi présent). Je suis intéressé par des solutions pour n'importe quelle version de GHC (y compris "ceci n'a été corrigé que dans GHC version V ").

14voto

Yuras Points 6145

Il n'est pas mis en œuvre parce que personne ne l'a demandé.

Ce qui est étrange, c'est que TH utilise son propre AST, qui ne suit pas l'AST du compilateur interne. Par conséquent, toute nouvelle fonctionnalité (par exemple, les familles de types associées) n'est pas automatiquement disponible via TH. Quelqu'un doit ouvrir un ticket et l'implémenter.

Pour la référence : interne reifyClass función ignore les familles de types associées (c'est le 5ème élément du tuple retourné par classExtraBigSig voir également la définition de ClassATItem .)

Techniquement, il devrait être facile de mettre en œuvre le support familial de type associé dans reify Mais il est fort probable qu'elle nécessitera des modifications incompatibles avec le passé dans l'API de TH, par exemple parce que son AST ne semble pas supporter les défauts de type associés.

Ajouté : Il est maintenant mis en œuvre (sans changement d'API d'ailleurs) et sera probablement disponible dans le prochain ghc libération.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X