gpt4 book ai didi

haskell - 使用 makeTokenParser 定义词法分析器时类型推断失败

转载 作者:行者123 更新时间:2023-12-02 12:44:31 26 4
gpt4 key购买 nike

我有以下代码:

module Lexer (lexer) where                                                                                                                                                                                                
import Text.Parsec
import Text.Parsec.Token
import Text.Parsec.Language

opChars = "<>+=*-/!:"

def = emptyDef {
commentStart = "/*"
, commentEnd = "*/"
, identStart = letter
, identLetter = alphaNum
, opStart = oneOf opChars
, opLetter = oneOf opChars
, reservedOpNames = ["+", "-", "*", "!=", "==", ":=", "<", "<=", ">", ">="]
, reservedNames = ["and", "not", "or", "p_", "when", "output", "of"]
}

lexer = makeTokenParser def

但是,当我尝试在 ghci 中导入此文件时,出现以下错误:

Prelude> :l Lexer.hs
[1 of 1] Compiling Lexer ( Lexer.hs, interpreted )

Lexer.hs:11:18:
No instance for (Stream s0 m0 Char) arising from a use of `letter'
The type variables `s0', `m0' are ambiguous
Relevant bindings include
def :: GenLanguageDef s0 u m0 (bound at Lexer.hs:8:1)
Note: there are several potential instances:
instance Monad m =>
Stream Data.ByteString.Internal.ByteString m Char
-- Defined in `Text.Parsec.Prim'
instance Monad m =>
Stream Data.ByteString.Lazy.Internal.ByteString m Char
-- Defined in `Text.Parsec.Prim'
instance Monad m => Stream Data.Text.Internal.Lazy.Text m Char
-- Defined in `Text.Parsec.Prim'
...plus two others
In the `identStart' field of a record
In the expression:
emptyDef
{commentStart = "/*", commentEnd = "*/", identStart = letter,
identLetter = alphaNum, opStart = oneOf opChars,
opLetter = oneOf opChars, reservedOpNames = ["+", "-", "*", ....],
reservedNames = ["and", "not", "or", ....]}
In an equation for `def':
def
= emptyDef
{commentStart = "/*", commentEnd = "*/", identStart = letter,
identLetter = alphaNum, opStart = oneOf opChars,
opLetter = oneOf opChars, reservedOpNames = ["+", "-", ....],
reservedNames = ["and", "not", ....]}

请注意,这仅在拆分文件后发生;我之前有一些代码在同一模块中消耗了“词法分析器”,然后将其分离出来。

我需要提供什么类型注释才能使其正常工作?

最佳答案

解决办法是注释:def::LanguageDef st。这会将 s0 修复为 String,将 m0 修复为 Identity

这是一个......宽松的解释。

让我们从外到内挑选类型。(这不一定是推理的工作方式,但我们通常拥有或可以获得顶级绑定(bind)的类型。)def 的推断类型为错误消息中注明:GenLanguageDef s0 u m0。查看 GenLanguageDef 的定义,因此 identStart 的推断类型为 ParsecT s0 u m0 Char

letter 的类型为 Stream s m Char => ParsecT s u m Char。将其与 identStart 类型统一,我们得到需要以某种方式满足的约束 Stream s0 m0 Char

monomorphism restriction禁止编译器简单地将推断的约束 float 到 def 的类型。禁用限制后,def 具有推断类型 Stream s0 m0 Char => GenLanguageDef s0 u m0。使用者可以修复类型变量,就像您在之前的单文件解决方案中所做的那样。

或者,提供我建议的具体签名只需修复变量 s0m0。现在编译器可以直接满足类约束,因为它知道 Identity 是一个 Monad 并且有一个实例 Monad m => Stream String m Char.

(您可能会认为,因为 emptyDef 的类型为 LanguageDef st,它会转换为 GenLanguageDef String st Identitydef 将具有该类型。啊,但是您使用的是记录更新语法,它允许更改类型变量。)

关于haskell - 使用 makeTokenParser 定义词法分析器时类型推断失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27285715/

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