在 megaparsec 7.0.4 中使用 parseTest
Using parseTest in megaparsec 7.0.4
Advent of Code 意味着我有一段时间以来第一次使用 megaparsec。自上次以来,情况发生了相当大的变化。假设
import qualified Text.Megaparsec as MP
import qualified Text.Megaparsec.Char as C
我试过了
MP.parseTest (C.char '+') "+"
在 GHCI 中,它给出了以下无用的错误消息:
interactive>:121:1: error:
* Ambiguous type variable `e0' arising from a use of `MP.parseTest'
prevents the constraint `(MP.ShowErrorComponent
e0)' from being solved.
Probable fix: use a type annotation to specify what `e0' should be.
These potential instance exist:
one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: MP.parseTest (C.char '+') "+"
In an equation for `it': it = MP.parseTest (C.char '+') "+"
<interactive>:121:15: error:
* Ambiguous type variable `e0' arising from a use of `C.char'
prevents the constraint `(Ord e0)' from being solved.
Probable fix: use a type annotation to specify what `e0' should be.
These potential instances exist:
instance (Ord a, Ord b) => Ord (Either a b)
-- Defined in `Data.Either'
instance Ord Ordering -- Defined in `ghc-prim-0.5.3:GHC.Classes'
instance Ord Integer
-- Defined in `integer-gmp-1.0.2.0:GHC.Integer.Type'
...plus 25 others
...plus 131 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `MP.parseTest', namely `(C.char '+')'
In the expression: MP.parseTest (C.char '+') "+"
In an equation for `it': it = MP.parseTest (C.char '+') "+"
我使用正确吗?我需要做什么来解决这个问题?
"megaparsec" 的最新版本支持 custom error types defined by the user. The ParsecT
type is parameterized by the type of the custom errors. To support pretty-printing (like in parseTest
) such custom errors must be instances of the Ord
and ShowErrorComponent
类型类。
如果我们从不抛出任何自定义错误,错误类型仍然是多态的。但最后,在打印结果时,我们必须提供一个具体的类型。我们可以使用 "void" 包中的无人类型 Void
,并通过使用显式类型签名通知类型检查器。
文档 recommends 定义了类型同义词 type Parser = Parsec Void Text
并在您的签名中使用它。
另一种避免歧义的方法是使用 visible type application:
Prelude Text.Megaparsec Data.Void> :t parseTest
parseTest
:: (ShowErrorComponent e, Show a, Stream s) =>
Parsec e s a -> s -> IO ()
Prelude Text.Megaparsec Data.Void> :set -XTypeApplications
Prelude Text.Megaparsec Data.Void> :t parseTest @Void
parseTest @Void
:: (Show a, Stream s) => Parsec Void s a -> s -> IO ()
Advent of Code 意味着我有一段时间以来第一次使用 megaparsec。自上次以来,情况发生了相当大的变化。假设
import qualified Text.Megaparsec as MP
import qualified Text.Megaparsec.Char as C
我试过了
MP.parseTest (C.char '+') "+"
在 GHCI 中,它给出了以下无用的错误消息:
interactive>:121:1: error:
* Ambiguous type variable `e0' arising from a use of `MP.parseTest'
prevents the constraint `(MP.ShowErrorComponent
e0)' from being solved.
Probable fix: use a type annotation to specify what `e0' should be.
These potential instance exist:
one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: MP.parseTest (C.char '+') "+"
In an equation for `it': it = MP.parseTest (C.char '+') "+"
<interactive>:121:15: error:
* Ambiguous type variable `e0' arising from a use of `C.char'
prevents the constraint `(Ord e0)' from being solved.
Probable fix: use a type annotation to specify what `e0' should be.
These potential instances exist:
instance (Ord a, Ord b) => Ord (Either a b)
-- Defined in `Data.Either'
instance Ord Ordering -- Defined in `ghc-prim-0.5.3:GHC.Classes'
instance Ord Integer
-- Defined in `integer-gmp-1.0.2.0:GHC.Integer.Type'
...plus 25 others
...plus 131 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the first argument of `MP.parseTest', namely `(C.char '+')'
In the expression: MP.parseTest (C.char '+') "+"
In an equation for `it': it = MP.parseTest (C.char '+') "+"
我使用正确吗?我需要做什么来解决这个问题?
"megaparsec" 的最新版本支持 custom error types defined by the user. The ParsecT
type is parameterized by the type of the custom errors. To support pretty-printing (like in parseTest
) such custom errors must be instances of the Ord
and ShowErrorComponent
类型类。
如果我们从不抛出任何自定义错误,错误类型仍然是多态的。但最后,在打印结果时,我们必须提供一个具体的类型。我们可以使用 "void" 包中的无人类型 Void
,并通过使用显式类型签名通知类型检查器。
文档 recommends 定义了类型同义词 type Parser = Parsec Void Text
并在您的签名中使用它。
另一种避免歧义的方法是使用 visible type application:
Prelude Text.Megaparsec Data.Void> :t parseTest
parseTest
:: (ShowErrorComponent e, Show a, Stream s) =>
Parsec e s a -> s -> IO ()
Prelude Text.Megaparsec Data.Void> :set -XTypeApplications
Prelude Text.Megaparsec Data.Void> :t parseTest @Void
parseTest @Void
:: (Show a, Stream s) => Parsec Void s a -> s -> IO ()