Search code examples
parsinghaskellparsec

parsec error with ambigious types


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?


Solution

  • 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.