haskell - 使用模板 Haskell 获取关联类型同义词

标签 haskell template-haskell type-families reify associated-types

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 也没有有关定义的信息:

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 和 template-haskell 包的 2.7.0.0 版本中。 (我没有检查 GHC 7.6.*,但我想它也存在于此。)我对任何版本的 GHC 的解决方案都感兴趣(包括“这仅在 GHC 版本中修复了V”)。

最佳答案

它没有实现,因为没有人请求它。

奇怪的是 TH 使用自己的 AST,它不遵循内部编译器的 AST。因此,任何新功能(例如关联的类型系列)都不会自动通过 TH 提供。必须有人开具票证并实现它。

供引用:内部reifyClass函数ignores关联类型族(它是 classExtraBigSig 返回的元组的第 5 个元素,另请参见 ClassATItem 的定义。)

从技术上讲,在 reify 中实现关联类型系列支持应该很容易,但很可能需要在 TH API 中进行向后不兼容的更改,例如因为它的 AST 似乎不支持关联的类型默认值。

已添加:现在是implemented (顺便说一句,无需更改 API)并且可能会在下一个 ghc 版本中提供。

关于haskell - 使用模板 Haskell 获取关联类型同义词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17247880/

相关文章:

haskell - 究竟是什么使类型系统保持一致?

list - 为什么任意大小的元组有用? (模板 Haskell)

haskell - Erlang 柯里化(Currying)函数

haskell - 如何用我自己生成的名称替换 `zs` 中的 `[p| zs@(z:_) |]` ?

haskell - 是否有用于引用的模板 haskell 函数?

haskell - 类型族导致不明确的变量错误

haskell - 类型族可以做什么多参数类型类和功能依赖不能

haskell - 索引子集中的类型族和单射性

haskell - 如何跟踪 Haskell 中的状态?

haskell - 为什么 EasyPlot 使命令在 GHCi 中不可见?