【发布时间】:2020-09-21 16:06:00
【问题描述】:
考虑最小化的代码:
module Parser where
import Text.ParserCombinators.Parsec
import Text.Parsec.Pos
oneTokenP f = token show (\_ -> initialPos "Dummy") f
oneToken t = token show (\_ -> initialPos (show t))
(\t' -> if t == t' then Just () else Nothing)
我得到错误:
Parser.hs:8:1: error:
• Non type-variable argument
in the constraint: Text.Parsec.Prim.Stream
s Data.Functor.Identity.Identity a1
(Use FlexibleContexts to permit this)
• When checking the inferred type
oneTokenP :: forall u s a a1.
(Show a1,
Text.Parsec.Prim.Stream s Data.Functor.Identity.Identity a1) =>
(a1 -> Maybe a) -> Text.Parsec.Prim.Parsec s u a
Parser.hs:9:1: error:
• Non type-variable argument
in the constraint: Text.Parsec.Prim.Stream
s Data.Functor.Identity.Identity a
(Use FlexibleContexts to permit this)
• When checking the inferred type
oneToken :: forall u s a.
(Eq a, Show a,
Text.Parsec.Prim.Stream s Data.Functor.Identity.Identity a) =>
a -> Text.Parsec.Prim.Parsec s u ()
我违反了哪个打字条件?
根据@amalloy 的建议重写:
oneTokenP f = token showTok posFromTok testTok
where
showTok (pos,t) = show t
posFromTok (pos,t) = initialPos "Dummy"
testTok (pos,t) = f t
oneToken x = token showTok posFromTok testTok
where
showTok (pos,t) = show t
posFromTok (pos,t) = initialPos (show t)
testTok (pos,t) = if x == t then Just () else Nothing
【问题讨论】:
-
解析器在其推断类型中有一个
Stream s Identity a约束。因为Identity是具体类型,而不是类型变量,所以这不是Haskell98,它要求约束的形式为Class var1 … varn。为此,您可以使用{-# LANGUAGE FlexibleContexts #-}pragma 或-XFlexibleContexts标志打开FlexibleContexts扩展; this 和FlexibleInstances(允许在instance定义中使用相同的东西)是非常良性的扩展并且非常常用。