Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why my haskell code copying from the book "Functional Programming in Haskell" can't be successfully interpreted?

Tags:

haskell

monads

The code is as below:

type Parser a = String -> [(a, String)]

retrn :: a -> Parser a
retrn v = \inp -> [(v, inp)]

parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp

item :: Parser Char
item = \inp -> case inp of
        []        -> []
        (x:xs)    -> [(x, xs)]

--problem code
p :: Parser (Char, Char)
p = do x <- item
       item
       y <- item
       retrn (x, y)

It gives the following type error:

SO-34035520.hs:19:8:
    Couldn't match type `[(Char, String)]' with `Char'
    Expected type: String -> [((Char, Char), String)]
      Actual type: Parser ([(Char, String)], [(Char, String)])
    In a stmt of a 'do' block: retrn (x, y)
    In the expression:
      do { x <- item;
           item;
           y <- item;
           retrn (x, y) }

What noteworthy is, the sample code that is on official website of the book can be interpreted smoothly, which is *.lhs format.

So, can somebody tell me why? I've been working on this struggle for days.

Thanks in advance.

like image 786
AhSeng Fan Avatar asked Jan 08 '23 02:01

AhSeng Fan


1 Answers

(->) String has a Monad instance but it is not what you are looking for. When you use do-notation in the definition of p, this instance is the one that is picked up.

What you want to do is make your own Monad instance for Parser (this requires changing it from a type synonym to a newtype wrapper over String -> [(a, String)]) and then let that be picked up in the definition of p.

Note that your example code already has an implementation of return (under the name of retrn) which does the right thing, and it is also very different from what return for (->) String is (which would be retrn v = \inp -> v.

like image 143
Cactus Avatar answered Jan 19 '23 06:01

Cactus