Parsec 简单解析器导致错误 "Non type-variable argument in the constraint: Stream s m Char"
Parsec simple parser results in error "Non type-variable argument in the constraint: Stream s m Char"
假设我只想创建自己的解析器,它与 Parsec 中的 char
完全相同,但是当我 运行
import Text.Parsec
char1 c = char c
它给了我
? Non type-variable argument in the constraint: Stream s m Char
(Use FlexibleContexts to permit this)
? When checking the inferred type
char1 :: forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Cha
我该如何解决?我应该包括任何其他进口商品吗?谢谢
Parsec 解析器由于其灵活性而具有相当复杂的类型。您可以通过两种方式解决此问题:
将 {-# Language FlexibleContexts #-}
放在源文件的顶部。这个 pragma 告诉 GHC 做一些额外的类型推断。
(推荐)给char1一个显式类型。
char1 :: Char -> Parsec String () Char
char1 c = char c
这是推荐的,因为您应该始终为任何顶级声明指定显式类型。如果你不这样做,那么所有编译器都会告诉你代码中某处存在类型不匹配(它会告诉你在哪里发现了矛盾,但不太可能是错误所在)。使用显式类型声明,编译器可以缩小范围。
在这种情况下,Parsec 将 Parsec
类型定义为
type Parsec s u = ParsecT s u Identity
您将从错误消息中认出 ParsecT
。 ParsecT
是一个 monad 转换器:当它识别文本时,它允许您让解析器在其他 monad(如 IO)中执行操作。在这种情况下,我们只需要一个解析器,所以我们使用 Identity
monad,它什么都不做。
s
参数是输入流。在这种情况下,我们会说解析器正在从 String
.
获取输入
u
参数是一个状态。这允许你做一些事情,比如在你遇到它们时在符号 table 中记录变量名。在这种情况下,我们不使用状态,所以它只是 ()
.
如果您正在编写一个真正的解析器,那么您通常会定义自己的类型同义词,例如
type FooParser a = Parsec Text FooState a
char1 :: Char -> FooParser Char
char1 = char
假设我只想创建自己的解析器,它与 Parsec 中的 char
完全相同,但是当我 运行
import Text.Parsec
char1 c = char c
它给了我
? Non type-variable argument in the constraint: Stream s m Char
(Use FlexibleContexts to permit this)
? When checking the inferred type
char1 :: forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Cha
我该如何解决?我应该包括任何其他进口商品吗?谢谢
Parsec 解析器由于其灵活性而具有相当复杂的类型。您可以通过两种方式解决此问题:
将
{-# Language FlexibleContexts #-}
放在源文件的顶部。这个 pragma 告诉 GHC 做一些额外的类型推断。(推荐)给char1一个显式类型。
char1 :: Char -> Parsec String () Char char1 c = char c
这是推荐的,因为您应该始终为任何顶级声明指定显式类型。如果你不这样做,那么所有编译器都会告诉你代码中某处存在类型不匹配(它会告诉你在哪里发现了矛盾,但不太可能是错误所在)。使用显式类型声明,编译器可以缩小范围。
在这种情况下,Parsec 将 Parsec
类型定义为
type Parsec s u = ParsecT s u Identity
您将从错误消息中认出 ParsecT
。 ParsecT
是一个 monad 转换器:当它识别文本时,它允许您让解析器在其他 monad(如 IO)中执行操作。在这种情况下,我们只需要一个解析器,所以我们使用 Identity
monad,它什么都不做。
s
参数是输入流。在这种情况下,我们会说解析器正在从 String
.
u
参数是一个状态。这允许你做一些事情,比如在你遇到它们时在符号 table 中记录变量名。在这种情况下,我们不使用状态,所以它只是 ()
.
如果您正在编写一个真正的解析器,那么您通常会定义自己的类型同义词,例如
type FooParser a = Parsec Text FooState a
char1 :: Char -> FooParser Char
char1 = char