gpt4 book ai didi

haskell - 一次更新两个记录字段时类型变量不明确(但更新一个记录字段时则不然!)

转载 作者:行者123 更新时间:2023-12-02 14:25:42 25 4
gpt4 key购买 nike

以下代码失败,并出现“类型变量不明确”错误(底部)。然而,更新记录两次的替代定义工作得很好:这是为什么呢?此外,下面的“损坏”定义与 Trifecta source 中的定义非常相似。 。我正在使用 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.

最佳答案

哈,这是一个有趣的问题。

这里的问题是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 时使用。 .

关于haskell - 一次更新两个记录字段时类型变量不明确(但更新一个记录字段时则不然!),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35037297/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com