下面的代码在出现“模棱两可的类型变量”错误(底部)时失败。但是,更新两次记录的另一个定义工作得很好:为什么会这样?此外,下面的“坏”定义与三层源区中的定义非常相似。我正在用GHC 7.10.3对trifecta 1.5.2和解析器0.12.3进行编译。
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
}以下是工作(可选)定义
identStyle :: TokenParsing m => IdentifierStyle m
identStyle = T.emptyIdents { _styleStart = letter } { _styleLetter = letter }第一个定义产生的错误是:
Main.hs:10:3:
Could not deduce (TokenParsing t0)
arising from a use of ‘emptyIdents’
from the context (TokenParsing m)
bound by the type signature for
identStyle :: TokenParsing m => IdentifierStyle m
at Main.hs:8:15-49
The type variable ‘t0’ is ambiguous
Note: there are several potential instances:
instance attoparsec-0.13.0.1:Data.Attoparsec.Internal.Types.Chunk
t =>
TokenParsing
(attoparsec-0.13.0.1:Data.Attoparsec.Internal.Types.Parser t)
-- Defined in ‘Text.Parser.Token’
instance TokenParsing Text.ParserCombinators.ReadP.ReadP
-- Defined in ‘Text.Parser.Token’
instance TokenParsing m => TokenParsing (Unhighlighted m)
-- Defined in ‘Text.Parser.Token’
...plus 11 others
In the expression: emptyIdents
In the expression:
emptyIdents {_styleStart = letter, _styleLetter = letter}
In an equation for ‘identStyle’:
identStyle
= emptyIdents {_styleStart = letter, _styleLetter = letter}
Failed, modules loaded: none.发布于 2016-01-27 19:05:52
哈,这是个有趣的问题。
这里的问题是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上修复此更新的最终类型并不能确定emptyIdents的类型。
有六种方法可以解决这个问题,但是基本的想法是,在构建emptyIdents时,您应该修复要使用的实例。
https://stackoverflow.com/questions/35037297
复制相似问题