获取与模板Haskell关联的类型同义词
Template Haskell能否找到类型类中声明的关联类型同义词的名称和/或声明?我原以为你会做我想做的,但它似乎没有提供所有必要的信息。它用于获取函数类型签名:获取与模板Haskell关联的类型同义词,haskell,template-haskell,type-families,reify,associated-types,Haskell,Template Haskell,Type Families,Reify,Associated Types,Template Haskell能否找到类型类中声明的关联类型同义词的名称和/或声明?我原以为你会做我想做的,但它似乎没有提供所有必要的信息。它用于获取函数类型签名: % 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
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)))])
[]
但是我首先找不到F
的名字。即使我添加类型类的实例,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)))
[]]
Prelude Language.Haskell.TH>实例C'[a],其中类型F[a]=a;f'=长度
前奏曲语言.Haskell.TH>f'“Haskell”
7.
前奏曲语言.Haskell.TH>42::F[整数]
42
Prelude Language.Haskell.TH>putStrLn$(stringE.show=没有实现,因为没有人请求它
奇怪的是TH使用自己的AST,它不遵循内部编译器的AST。因此,任何新功能(例如关联的类型族)都不能通过TH自动使用。有些人必须打开一个票证并实现它
参考:internalreifyClass
函数关联类型族(它是返回的元组的第5个元素,另请参见的定义。)
从技术上讲,在具体化中实现关联的类型系列支持应该很容易,但很可能需要在TH API中进行向后不兼容的更改,例如,因为它的AST似乎不支持关联的类型默认值
添加:它现在(顺便说一句,没有API更改)可能会在下一个ghc
版本中提供。你看过reifyInstances
了吗?@kwartz:我现在刚试过。但是它不起作用;它只是产生了与reify
:putStrLn相同的实例$(stringE.show=我觉得奇怪的是,reify
没有返回必要的信息。也许show
隐藏了一些信息?您是否尝试过直接检查Info
对象?@kwartz:恐怕Info
的show
实例只是派生的一个,而show
例如Dec
。但是,我也可以直接检查,正如你所问,否:putStrLn$(具体化'C'>=\I->ClassI的第一个案例(ClassD.\uuuuud.[SigD.\uuud]->stringE“只是一个SigD”;\uud->stringE“其他的东西”)
产生只是一个SigD
——这是[Dec]中唯一的东西
在ClassD
!(需要LambdaCase
)中。我同意这很奇怪;这就是我问这个问题的原因:-)@Abel:我想我们达成了激烈的一致——你最初的评论说这不足以吸引一个绝妙的想法,但它确实吸引了Yuras的答案!我完全同意好的答案是:-)@AntalS-Z我的意思是FamilyD
不支持。您可能没有使用它们,但完整的解决方案可能需要更改API。@Abel,将悬赏保留到最后也有助于好答案吸引选票,因此奖励好答案比快速奖励好答案更有效。悬赏期已过。这是最好的方法(且仅限于)回答,直到或除非。在回答中包含错误报告的链接可能是个好主意。仅供参考,#10891已修复,正在等待合并。@SwiftsNames AFAIK ghc开发者希望在不破坏API的情况下自由更改内部AST。可能还有其他原因。
Prelude Language.Haskell.TH> putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
Ghci3.F
[PlainTV a_1627405973]
(Just StarT))
[]
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)))
[]]