1

I have the following parsers functions

import Data.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

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

(+++) :: Parser a -> Parser a -> Parser a
p +++ q = \inp -> case parse p inp of
            [] -> parse q inp
     [(v,out)] -> [(v,out)]

So far so good, they can be loaded into ghci. But when I add the following function

sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           if p x then return x else failure

I obtain an error. Could you tell what's going on?

2
  • The function is called return' not return. Commented Dec 30, 2014 at 20:08
  • My bad, but I'm still obtain an error, it goes like this: No instance for (Monad ((->) String) arising from a do statement Commented Dec 30, 2014 at 20:13

2 Answers 2

1

The type of x in the do block of sat is [(Char, String)]. This is because item has the type String -> [(Char, String)] or (->) String [(Char, String)] and you are using the Monad instance for (->) String, so what is "contained" in a (->) String [(Char, String)] is a [(Char, String)].

{-# LANGUAGE ScopedTypeVariables #-}

sat :: (Char -> Bool) -> Parser Char
sat p = do (x :: [(Char, String)]) <- item
           if p x then return' x else failure

p is a function from a Char to Bool; it doesn't accept a list of possible parsing results. The only sensible thing to do with p is filter the results based on whether the Char matches p. This still results in [] when the result doesn't match p.

sat :: (Char -> Bool) -> Parser Char
sat p = do (x :: [(Char, String)]) <- item
           return $ filter (p . fst) x

If we drop ScopedTypeVariables, we need to drop the type signature I added for illustration.

sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
           return $ filter (p . fst) x
Sign up to request clarification or add additional context in comments.

Comments

0

Use of do blocks requires that your Parser is an instance of the Monad class. Since your Parser type is an alias for a function type String -> [(a, String)] and functions are not instances of Monad, this is why you get the error. You could write your function without using do notation:

sat :: (Char -> Bool) -> Parser Char
sat p [] = []
sat p (c:cs) = if p c then [(c, cs)] else []

1 Comment

Functions are instances of Monad, or have been since base 4.6.0.0. Before that the Monad instance for functions was given by instance Monad ((->) r) where return = const; f >>= k = \r -> k (f r) r in Control.Monad.Instances.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.