Parser as an instance of the monad class

I am working my way through Graham Hutton's book and find that his approach to introducing monads is rather nice. Trouble is that the code there does not work "out of the book". Specifically, if you define the Parser type as follows: type Parser a :: String -> [(a,String)] you can then define the return and bind functions as return v = \x -> [(v,x)] p >>= f = \x -> case p x of [] -> [] [(v,y)] -> (f v) y but you get name conflicts with the functions of the same names in the Prelude. Fair enough. There are a number of ugly things that you can do at this point that are just plain wrong, so I thought that the right thing to do would be to get the Parser type to be manifested as an instance of the Monad class. Ok, now what? Since Parser is only a type synonym it cannot be used directly in the following way: instance Monad Parser where return v = . . . p >>= f = . . . but since Parser is not an algebraic type as it is defined that won't work either. So how do you do it? help . ::paul

On Tue, Jan 11, 2011 at 11:39:48PM -0800, Paul Higham wrote:
There are a number of ugly things that you can do at this point that are just plain wrong, so I thought that the right thing to do would be to get the Parser type to be manifested as an instance of the Monad class. Ok, now what? Since Parser is only a type synonym it cannot be used directly in the following way:
instance Monad Parser where return v = . . . p >>= f = . . .
but since Parser is not an algebraic type as it is defined that won't work either. So how do you do it? help .
Have you looked at the book's website? He provides the entire Parsing.lhs library, and you can see there an example of how to do it. regards, iustin

I Just looked at it after your suggestion, Maybe I should have looked at it before, because it's way better than the Nothing I was using! Thanx for the tip, ::paul On Jan 12, 2011, at 12:01 AM, Iustin Pop wrote:
On Tue, Jan 11, 2011 at 11:39:48PM -0800, Paul Higham wrote:
There are a number of ugly things that you can do at this point that are just plain wrong, so I thought that the right thing to do would be to get the Parser type to be manifested as an instance of the Monad class. Ok, now what? Since Parser is only a type synonym it cannot be used directly in the following way:
instance Monad Parser where return v = . . . p >>= f = . . .
but since Parser is not an algebraic type as it is defined that won't work either. So how do you do it? help .
Have you looked at the book's website? He provides the entire Parsing.lhs library, and you can see there an example of how to do it.
regards, iustin

On Tue, Jan 11, 2011 at 11:39:48PM -0800, Paul Higham wrote:
I am working my way through Graham Hutton's book and find that his approach to introducing monads is rather nice. Trouble is that the code there does not work "out of the book". Specifically, if you define the Parser type as follows:
type Parser a :: String -> [(a,String)]
you can then define the return and bind functions as
return v = \x -> [(v,x)] p >>= f = \x -> case p x of [] -> [] [(v,y)] -> (f v) y
but you get name conflicts with the functions of the same names in the Prelude. Fair enough.
There are a number of ugly things that you can do at this point that are just plain wrong, so I thought that the right thing to do would be to get the Parser type to be manifested as an instance of the Monad class. Ok, now what? Since Parser is only a type synonym it cannot be used directly in the following way:
instance Monad Parser where return v = . . . p >>= f = . . .
but since Parser is not an algebraic type as it is defined that won't work either. So how do you do it? help .
Make Parser a newtype, like so: newtype Parser a = Parser (String -> [(a, String)]) Now you will have some extra Parser constructors to deal with, but you can make this an instance of Monad just fine. -Brent

And thanx to you also, this is starting to make some sense ::paul On Jan 12, 2011, at 5:49 AM, Brent Yorgey wrote:
On Tue, Jan 11, 2011 at 11:39:48PM -0800, Paul Higham wrote:
I am working my way through Graham Hutton's book and find that his approach to introducing monads is rather nice. Trouble is that the code there does not work "out of the book". Specifically, if you define the Parser type as follows:
type Parser a :: String -> [(a,String)]
you can then define the return and bind functions as
return v = \x -> [(v,x)] p >>= f = \x -> case p x of [] -> [] [(v,y)] -> (f v) y
but you get name conflicts with the functions of the same names in the Prelude. Fair enough.
There are a number of ugly things that you can do at this point that are just plain wrong, so I thought that the right thing to do would be to get the Parser type to be manifested as an instance of the Monad class. Ok, now what? Since Parser is only a type synonym it cannot be used directly in the following way:
instance Monad Parser where return v = . . . p >>= f = . . .
but since Parser is not an algebraic type as it is defined that won't work either. So how do you do it? help .
Make Parser a newtype, like so:
newtype Parser a = Parser (String -> [(a, String)])
Now you will have some extra Parser constructors to deal with, but you can make this an instance of Monad just fine.
-Brent
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Brent Yorgey
-
Iustin Pop
-
Paul Higham