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").
reifyInstances?InstanceDs as I saw withreify:putStrLn $(stringE . show =<< reifyInstances ''C' =<< sequence [[t|[Int]|]])evaluates to[InstanceD [] (AppT (ConT Ghci1.C') (AppT ListT (VarT a_1627405978))) []], which lacks the type family instances.reifydoesn't return the necessary information. Perhapsshowis hiding some of the information? Have you tried examining theInfoobject directly?Info'sShowinstance is just the derived one, and same for theShowinstance forDec. However, I can also check directly, as you asked, and no:putStrLn $(reify ''C' >>= \i -> case i of ClassI (ClassD _ _ _ _ [SigD _ _]) _ -> stringE "just a SigD" ; _ -> stringE "something else")producesjust a SigD– that's really the only thing in the[Dec]in theClassD! (requiresLambdaCase). I agree it's odd; that's why I asked this question :-)