Getting associated type synonyms with template Haskell
Can Template Haskell find out the names and/or the declarations of the associated type synonyms declared in a type class? I expected reify
would do what I want, but it doesn't seem to provide all the necessary information. It works for getting function type signatures:
% 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)))])
[]
However, adding an associated type synonym to the class causes no change (up to renaming) in the 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)))])
[]
If I know the name of F
, I can look up information about it:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
But I can't find the name of F
in the first place. Even if I add an instance of the type class, the InstanceD
has none of the information about the 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)))
[]]
If reify
won't work, is there a workaround, other than listing the associate type synonyms manually?
This problem is present in GHC 7.8.3 with version 2.9.0.0 of the template-haskell package; it was also present in GHC 7.4.2 with version 2.7.0.0 of the template-haskell package. (I didn't check on GHC 7.6.*, but I imagine it was present there too.) I'm interested in solutions for any version of GHC (including "this was only fixed in GHC version V").
Solution 1:
It is not implemented because nobody requested it.
The odd thing is that TH uses its own AST, which doesn't follow internal compiler's AST. As a result, any new feature (e.g. associated type families) is not automatically available via TH. Some one have to open a ticket and implement it.
For the reference: internal reifyClass
function ignores associated type families (it is the 5th element of the tuple returned by classExtraBigSig
, see also definition of ClassATItem
.)
Technically it should be easy to implement associated type family support in reify
, but most likely it will require backward incompatible changes in TH API, e.g. because its AST doesn't seem to support associated type defaults.
Added: It is now implemented (without API change btw) and probably will be available in the next ghc
release.