以下代码因“模糊类型变量”错误而失败(底部)。但是,两次更新记录的替代定义很好:这是为什么?此外,下面的“破坏”定义与Trifecta source中的定义非常相似。我正在使用GHC 7.10.3编译三分法1.5.2和解析器0.12.3。
#data-table {
margin: 20px 0;
}
这是工作(替代)定义
20px
第一个定义产生的错误是:
module Main where
import Text.Trifecta
import Text.Parser.Token.Style as T
-- This definition causes a type error
identStyle :: TokenParsing m => IdentifierStyle m
identStyle =
T.emptyIdents
{ _styleStart = letter
, _styleLetter = letter
}
答案 0 :(得分:4)
这里的问题是emptyIdents
是类多态的。因此,当您使用它时,类型推断算法的某些部分必须定义要使用的实例。
当您一次只修改一个字段时,不允许更改记录的类型;也就是说,\record -> record { _styleStart = undefined }
的类型是IdentifierStyle m -> IdentifierStyle m
。所以通过要求最终类型的
emptyIdents { _styleStart = letter } { _styleLetter = letter }
是IdentifierStyle m
,我们可以推断第一个emptyIdents
也是IdentifierStyle m
,其类型m
与参数相同。
另一方面,由于记录更新在Haskell中的工作原理,当您一次更新两个字段时(恰好是其类型提及类型参数m
的所有字段),更新变为多态。也就是说,\record -> record { _styleStart = undefined, _styleLetter = undefined }
的类型是IdentifierStyle m' -> IdentifierStyle m
- 注意素数!
因此,如果您同时进行两次更新,例如
emptyIdents { _styleStart = letter, _styleLetter = letter }
然后在IdentifierStyle m
修复此更新的最终类型吗 not 确定emptyIdents
的类型。
有六种方法可以解决这个问题,但基本的想法是你应该在构建emptyIdents
时修复要使用的实例。