
Hello list, I have a rather trivial question, but one that I can't seem to get my head around. In the following example function (using Text.ParserCombinators.Parsec) I'm getting an error without the type declaration, but it compiles just fine with it:
parseNumber' :: Parser LispVal parseNumber' = do x <- many1 digit return $ Number . read $ x
The error message when compiling without the type declaration is the following: No instance for (Text.Parsec.Prim.Stream s m Char) arising from a use of `digit' at Scheme.hs:33:30-34 Possible fix: add an instance declaration for (Text.Parsec.Prim.Stream s m Char) In the first argument of `many1', namely `digit' In a stmt of a 'do' expression: x <- many1 digit In the expression: do { x <- many1 digit; return $ Number . read $ x } The function is an example in "Write yourself a Scheme in 48 hours." I'd consider myself fairly accustomed to programming with monads; and still, I can't seem to find out *why* exactly GHC ( 6.12.1 ) cannot compile this without the type signature. What does it try to build here? Why does the inferencing fail? My best guess is that it somehow doesn't get that 'x' is supposed to be a String value ([Char], not Char.) What really confuses me, though, is that adding the instance declaration makes the whole thing work! The type declaration for LispVal looks like this:
data LispVal = Number Integer
So it should be pretty clear to GHC that, due to `Number . read` demanding a [Char], I actually want x to be a [Char]. I'm assuming here that I'm just in the wrong Monad, starting with `do`. Somehow, GHC assumes it's not Parser LispVal, but something more complex, possibly Text.Parsec.Prim.Stream s m LispVal or so? Thank you everybody for you help :-) This list is a truly amazing place with a lot of helpful people! Aleks

Hi Aleksandar This line looks wrong
return $ Number . read $ x
Try this
return $ Number $ read x
If that doesn't work then I'm not sure. The tutorial was written for Parsec 2 but it looks like you are using Parsec 3. In practice there aren't many differences to users at least once you import the right see of modules (the modules to import are slightly different). Maybe you could post your whole module if there are still problems. Best wishes Stephen

Further... If you are using Strings (rather than ByteStrings) you want to import this module with Parsec 3: import Text.Parsec.String This should bring in the right instances for Stream. You may have to import other modules as well for particular parsers.

On 10 July 2010 10:54, Magnus Therning
AFAICS that change should make no difference at all. In fact the line could also be written as
return . Number . read $ x
Yeah - it was a rather poor answer especially as on a proper reading the original poster's question was even asking about that... Here's a better answer: Starting from the line: x <- many1 digit Without a type decl, at this point x :: [a]. /a/ is constrained, as the parsers answer type as the whole computation is with the ParsecT monad transformer. But other than that /a/ is polymorphic. The next line with the read obliges x to be a String (for read to type check): return $ Number . read $ x But this is not enough to give a full type to the whole computation, with the lifting to Number of the "x" the type of the whole function is going to be :: ParsecT s m Number. The stream type /s/ and the monad type /m/ are not resolved. Adding a type signature with the Parser type in Parsec 3 resolves the types of the stream and monad via 2 type synonyms: type Parser = Parsec String () type Parsec s u = ParsecT s u Identity where u is a further type parameter for user state. The base monad is resolved to Identity, the stream is resolved to String.
participants (3)
-
Aleksandar Dimitrov
-
Magnus Therning
-
Stephen Tetley