Help with Programming in Haskell example

Hello I've been reading Programming in Haskell, and I'm trying to go through the parser examples in chapter. However, I'm getting a type error when using the "do" notation. Here's the code I'm trying to load in ghci, which is copied from the book: import Prelude hiding ((>>=), return) import Char type Parser a = String -> [(a, String)] return :: a -> Parser a return v = \inp -> [(v, inp)] failure :: Parser a failure = \inp -> [] item :: Parser Char item = \inp -> case inp of [] -> [] (x:xs) -> [(x, xs)] parse :: Parser a -> String -> [(a, String)] parse p inp = p inp (>>=) :: Parser a -> (a -> Parser b) -> Parser b p >>= f = \inp -> case parse p inp of [] -> [] [(v, out)] -> parse (f v) out p :: Parser (Char, Char) p = do x <- item item y <- item return (x, y) The problem is in the definition of "p": Couldn't match expected type `Char' against inferred type `[(Char, String)]' In the expression: x In the first argument of `return', namely `(x, y)' In the expression: return (x, y) Now if I define p as p :: Parser (Char, Char) p = item >>= \x -> item >>= \_ -> item >>= \y -> return (x, y) it works fine, so I'm wondering what else I need to do for the "do" notation to work. Thanks in advance, Andre

Hello, Andre Nathan schrieb:
so I'm wondering what else I need to do for the "do" notation to work.
import Prelude hiding ((>>=), return)
You explicitly ask for the well-known and standard functions >>= and return to be hidden away, because you want to define your own versions.
p :: Parser (Char, Char) p = do x <- item item y <- item return (x, y)
The do-notation is desugared to some calls of the well-known and standard functions >>= and return, defined in the Prelude. Wich are different from your own functions >>= and return. So you have to connect your definitions of >>= and return to the well-known functions used by the do notation. To do so, you have to declare your Parser type an instance of the somewhat magic do-notation-enableing typeclass Monad. Fortunately, this is not too hard, because you can reuse your functions >>= and return. First, change your Parser type to be a proper data type instead of a type synonym (and change your code to correctly pack / unpack Parser values):
data Parser a = Parser (String -> [(a, String)])
Second, move >>= and return inside an instance declaration:
instance Monad Parser where (Parser p) >>= f = ... return v = Parser (\inp -> [(v, inp)])
Third, stop hiding Prelude's >>= and return.
import Prelude
Now you should be able to use do notation with your own Parser type. Tillmann

On Fri, 2007-05-18 at 22:32 +0200, Tillmann Rendel wrote:
[snip] Now you should be able to use do notation with your own Parser type.
Thanks! Monads and instances weren't mentioned until that point, so I was assuming that all that was needed for the "do" notation to work was having "(>>=)" and "return" defined... Best regards, Andre
participants (2)
-
Andre Nathan
-
Tillmann Rendel