为什么DuplicateRecordFields不能进行类型推断?

时间:2016-12-07 02:12:00

标签: haskell types ghc records

相关文章:How to disambiguate selector function?

https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields

  

但是,我们不推断参数的类型来确定数据类型,或者有任何方法可以将选择推迟到约束求解器。

实际上很烦人,这个功能没有实现。我试图查找多个来源,但我找不到他们决定不推断类型的原因。

有谁知道这个的好理由?是因为当前类型系统的限制吗?

1 个答案:

答案 0 :(得分:9)

您将对仍在实施的OverloadedRecordFields感兴趣。

目前的实施有意削弱,以免一次性引入太多新东西。推断记录投影类型最终会打开一堆令人讨厌的蠕虫(前面提到的扩展地址)。

考虑以下GHCi互动

ghci> data Record1 = Record1 { field :: Int }
ghci> data Record2 = Record2 { field :: Bool }
ghci> :t field

现在field的类型应该是什么?不知何故,我们需要一种方法来捕捉"任何带有field"字段的记录的概念。为此,OverloadedRecordFields引入了一个新的内置类型类

  

新模块GHC.Records定义以下内容:

class HasField (x :: k) r a | x r -> a where
  getField :: r -> a
     

HasField x r a约束表示x是一个字段的事实   输入属于记录类型a的{​​{1}}。 r方法给出了   记录选择器功能。

然后,从我们上面的例子中,好像GHC神奇地生成了以下实例(事实上实际上并不会发生什么,但这是一个很好的初步近似)。

getField

如果您有兴趣,我建议您阅读该提案。我还没有提到的另一个功能是instance HasField "field" Record1 Int where getField (Record1 f) = f instance HasField "field" Record2 Bool where getField (Record2 f) = f 类。一旦实现所有这些(以及更多用于更新记录),我期待能够get my lenses for free(因此我可以停止声明以下划线开头的字段名称并为{{1}启用IsLabel })。