首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当一次更新两个记录字段时,不明确的类型变量(但不是更新一个!)

当一次更新两个记录字段时,不明确的类型变量(但不是更新一个!)
EN

Stack Overflow用户
提问于 2016-01-27 12:23:24
回答 1查看 421关注 0票数 3

下面的代码在出现“模棱两可的类型变量”错误(底部)时失败。但是,更新两次记录的另一个定义工作得很好:为什么会这样?此外,下面的“坏”定义与三层源区中的定义非常相似。我正在用GHC 7.10.3对trifecta 1.5.2和解析器0.12.3进行编译。

代码语言:javascript
复制
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
    }

以下是工作(可选)定义

代码语言:javascript
复制
identStyle :: TokenParsing m => IdentifierStyle m
identStyle = T.emptyIdents { _styleStart = letter } { _styleLetter = letter }

第一个定义产生的错误是:

代码语言:javascript
复制
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.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-27 19:05:52

哈,这是个有趣的问题。

这里的问题是emptyIdents是类多态的.因此,当您使用它时,类型推断算法的某些部分必须定义要使用的实例。

当一次只修改一个字段时,不允许更改记录的类型;也就是说,\record -> record { _styleStart = undefined }的类型是IdentifierStyle m -> IdentifierStyle m。所以通过要求最后一种

代码语言:javascript
复制
emptyIdents { _styleStart = letter } { _styleLetter = letter }

如果是IdentifierStyle m,我们可以推断第一个emptyIdents也是IdentifierStyle m,与参数具有相同的m类型。

另一方面,由于Haskell中记录更新的工作方式,当您同时更新两个字段(恰好是所有类型都提到类型参数m的字段)时,更新就变得多态了。也就是说,\record -> record { _styleStart = undefined, _styleLetter = undefined }的类型是IdentifierStyle m' -> IdentifierStyle m --注意质数!

因此,在同时进行两次更新的情况下,如

代码语言:javascript
复制
emptyIdents { _styleStart = letter, _styleLetter = letter }

那么,在IdentifierStyle m上修复此更新的最终类型并不能确定emptyIdents的类型。

有六种方法可以解决这个问题,但是基本的想法是,在构建emptyIdents时,您应该修复要使用的实例。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35037297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档