使用模板Haskell获取关联的类型同义词
Can Template Haskell可以找出类型类中声明的关联类型同义词的名称和/或声明吗? 我期望reify
会做我想做的事情,但它似乎并没有提供所有必要的信息。 它适用于获取函数类型签名:
% 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)))])
[]
但是,向类中添加关联类型同义词不会导致输出中的更改(重命名):
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)))])
[]
如果我知道F
的名字,我可以查找关于它的信息:
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
但是我首先找不到F
的名字。 即使我添加了一个类型的InstanceD
, InstanceD
也没有关于该定义的信息:
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)))
[]]
如果reify
不起作用,是否有解决方法,除了手动列出关联类型同义词?
GHC 7.8.3中使用template-haskell包的版本2.9.0.0存在此问题; 它也出现在GHC 7.4.2中,模板-haskell包的版本为2.7.0.0。 (我没有检查GHC 7.6。*,但我想它也出现在那里)。我对GHC的任何版本的解决方案感兴趣(包括“这只在GHC版本V中修复”)。
它没有被执行,因为没有人请求它。
奇怪的是TH使用它自己的AST,它不遵循内部编译器的AST。 因此,任何新功能(例如关联类型系列)都不能通过TH自动提供。 有人必须打开票并实施它。
对于参考:内部reifyClass
函数会忽略关联的类型系列(它是classExtraBigSig
返回的元组的第5个元素,另请参阅ClassATItem
定义。)
从技术上讲,在reify
实现关联类型系列支持应该很容易,但很可能它需要在TH API中向后兼容更改,例如因为它的AST似乎不支持关联类型默认值。
补充:现在已经实现了(没有API更改btw),并且可能会在下一个ghc
版本中提供。