Reputation: 3451
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?
Upvotes: 1
Views: 396
Reputation: 144106
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 []
Upvotes: 0
Reputation: 24156
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
Upvotes: 1