0
votes

I'm writing a wiki parser using haskell and I have run into this wierd problem. My code right now looks like this

import System.Environment
import Control.Applicative hiding ((<|>), many)

import Control.Monad
import Text.Parsec
import Text.Parsec.String
import Text.Parsec.ByteString.Lazy

data RichText = UText String
              | DText String
              deriving (Show)

parseBold = do
  string "\'\'\'"
  manyTill anyChar (try (string "\'\'\'"))

parseItalic = do
  string "\'\'"
  manyTill anyChar (try (string "\'\'"))

parsefunc content = do
  case (parse parseItalic "parsing" content) of
    Right result -> return result
    Left error -> return "some error!"

main = do
  content:_ <- getArgs
  result <- parsefunc content
  print result

If I comment out parseItalic and use parseBold, it works. If I comment out parseBold and use parseItalic, it works. But both don't work at the same time... It throws an error

   No instance for (Stream s0 m0 Char) arising from a use of `string'
   The type variables `s0', `m0' are ambiguous
   Relevant bindings include
     parseBold :: ParsecT s0 u m0 [Char] (bound at wi.hs:13:1)
   Note: there are several potential instances:
     instance Monad m => Stream [tok] m tok
       -- Defined in `Text.Parsec.String'
     instance Monad m =>
              Stream Data.ByteString.Lazy.Internal.ByteString m Char
       -- Defined in `Text.Parsec.ByteString.Lazy'
     instance Monad m =>
              Stream Data.ByteString.Internal.ByteString m Char
       -- Defined in `Text.Parsec.ByteString'
   In a stmt of a 'do' block: string "'''"
   In the expression:
     do { string "'''";
          manyTill anyChar (try (string "'''")) }
   In an equation for `parseBold':
       parseBold
         = do { string "'''";
                manyTill anyChar (try (string "'''")) }

I'm not able to understand what is this error. Obviously my type is a string (which is nothing but [Char]) but why is the compiler complaining that it is Char?

2

2 Answers

1
votes

You have imported both

import Text.Parsec.String
import Text.Parsec.ByteString.Lazy

The former parses "Stream Char" and the latter "Stream Word8". So you have to get rid of ByteString.Lazy to leave just one variant. If you need both (e.g. you intend to parse ByteString as well as String using polymorphic functions), you have to explicitly parametrise Stream.

0
votes

There is an ambiguity error.

The type of the parsers can be either Text.Parsec.String.Parser or Text.Parsec.ByteString.Lazy.Parser, and the compiler doesn't know which to choose.

You can get the code to compile if you add the types....

parseBold::Text.Parsec.ByteString.Lazy.Parser String
parseBold = do
....etc

There are other ways to fix the ambiguity....

You could use parseBold/parseItalic somewhere else where the types would be inferred, or you could clean up the imports so that only one case is allowed.