Advent of Code means I'm using megaparsec for the first time in a while. And things have changed around a fair bit since last time. Assuming
import qualified Text.Megaparsec as MP
import qualified Text.Megaparsec.Char as C
I tried
MP.parseTest (C.char '+') "+"
in GHCI, which gives the following rather unhelpful error message:
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 '+') "+"
Am I using this correctly? What do I need to do to fix this?
The latest versions of "megaparsec" support 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
typeclasses.
If we never throw any custom errors, the error type remains polymorphic. But at the end, when printing the results, we must provide a concrete type. We can use the uninhabited type Void
from the "void" package, and inform the type checker by using an explicit type signature.
The documentation recommends defining a type synonym like type Parser = Parsec Void Text
and using it in your signatures.
Another way of avoiding the ambiguity is by using 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 ()