0

代码的出现意味着我有一段时间第一次使用 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 '+') "+"

我正确使用它吗?我需要做什么来解决这个问题?

4

1 回答 1

1

最新版本的“megaparsec”支持用户定义的自定义错误类型。类型由自定义错误的ParsecT类型参数化。为了支持漂亮的打印(如 in parseTest),此类自定义错误必须是Ord和类型类的实例ShowErrorComponent

如果我们从不抛出任何自定义错误,则错误类型仍然是多态的。但最后,在打印结果时,我们必须提供一个具体的类型。我们可以使用“void”包中的无人居住类型Void,并使用显式类型签名通知类型检查器。

该文档建议定义一个类型同义词type Parser = Parsec Void Text,并在您的签名中使用它。

避免歧义的另一种方法是使用可见类型应用程序

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 ()
于 2018-12-01T12:28:46.637 回答