Functional Parser example in Haskell using GHCi - haskell

I am a beginner of learning Haskell. Here is the problem I've encountered when using GHCi.
p :: Parser (Char, Char)
p = do x <- item
item
y <- item
return (x,y)
item :: Parser Char
item = P (\inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)])
item is another parser where item :: Parser Char, simply item is to parse a string
When I load the file then execute
parse p "abcdef"
An execption is then shown:
*** Exception: You must implement (>>=)
Any idea for fixing such problem ?
Updated information:
The Parser is defined as follow:
newtype Parser a = P (String -> [(a,String)])
instance Monad Parser where
return :: a -> Parser a
return v = P (\inp -> [(v,inp)])
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
p >>= f = --...

In order to use do notation, your Parser must be an instance of Monad:
instance Monad Parser where
return :: a -> Parser a
return = -- ...
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
p >>= f = -- ...
The compiler needs you to fill in definitions of return and >>=.
do notation is syntatic sugar that desugars to use of >>= (pronounced "bind"). For example, your code desugars to:
p :: Parser (Char, Char)
p = item >>= \x ->
item >>= \_ ->
item >>= \y ->
return (x,y)
Or, with more explicit parentheses:
p = item >>= (\x -> item >>= (\_ -> item >>= (\y -> return (x,y))))
>>= describes how to combine a Parser a along with a function a -> Parser b to create a new Parser b.
Using your definition of Parser, a working Monad instance is
instance Monad Parser where
return a = P $ \s -> [(a,s)]
p >>= f = P $ concatMap (\(a,s') -> runParser (f a) s') . runParser p
-- which is equivalent to
-- p >>= f = P $ \s -> [(b,s'') | (a,s') <- runParser p s, (b,s'') <- runParser (f a) s']
Consider what >>= does in terms of a p :: Parser a and a function f :: a -> Parser b.
when unwrapped, p takes a String, and returns a list of (a,String) pairs
runParser p :: String -> [(a,String)]
for each (a,String) pair, we can run f on the a to get a new parser q:
map go . runParser p :: String -> [(Parser b,String)]
where go :: (a, String) -> (Parser b, String)
go (a,s') = let q = f a in (q, s')
if we unwrap q, we get a function that takes a String and returns a list of (b, String) pairs:
map go . runParser p :: String -> [(String -> [(b,String)],String)]
where go :: (a, String) -> (String -> [(b,String)],String)
go (a,s') = let q = f a in (runParser q, s')
we can run that function on the String that was paired with the a to get our list of `(b, String) pairs immediately:
map go . runParser p :: String -> [[(b,String)]]
where go :: (a, String) -> [(b,String)]
go (a,s') = let q = f a in runParser q s'
and if we flatten the list-of-lists that results we get an String -> [(b,String)], which is just unwrapped Parser b
concat . map go . runParser p :: String -> [(b,String)]
where go :: (a, String) -> [(b,String)]
go (a,s') = let q = f a in runParser q s'

Related

Haskell traverse and filter through a list while lifting results

Say I have code where I want to do the following:
Input: a list of strings [String]
Operation (checkSat and checkResult)
Obtains a boolean from an input string.
Output:
If everything in the input is parseable into a boolean, only return those that resulted in "unsat".
If at least one of them has an error, return an error.
data Err = Err String deriving (Show)
-- Detail omitted for this example
checkSat :: String -> Either Err String
checkSat = Right . id
checkResult :: String -> Either Err Bool
checkResult "sat" = Right True
checkResult "unsat" = Right False
checkResult err = Left $ Err err
onlyUnsat :: [String] -> Either Err [String]
onlyUnsat xs = filter (traverse notSat xs) xs
where notSat x = fmap not $ checkSat x >>= checkResult
onlyUnsat = filter (traverse notSat xs) xs
The code above doesn't quite work. What's the right way to write onlyUnsat with the correct typing?
Try this:
onlyUnsat :: [String] -> Either Err [String]
onlyUnsat = traverse checkSat >=> filterM (fmap not . checkResult)
where
filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
filterM p = fmap (map fst . filter snd) . traverse (\x -> withFst x <$> p x)
where withFst x = \y -> (x, y)
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
Note that both filterM and >=> can be imported from Control.Monad. I've redefined them here for the sake of clarity :-)
The basic idea is to split the operation into two stages: (1) apply checkSat on every item in the list; and (2) filter every item in the list. The first stage is given by traverse checkSat, which has type [String] -> Either Err [String]. The second stage is given by filterM (fmap not . checkResult), which also has type [String] -> Either Err String. We then use >=> to chain these two computations together into one of the same type.

haskell return [] for data from a parser function

In the code below, I am supposed to get [] after running parse noun:
parse noun "something" = []
Unfortunately I can not change the signature of the function so Maybe is not an option.
How can I return [] from the noun function when running
parse noun "something"
?? (I don't want to return the 'c' variable)
Many thanks for your help.
import Parsing
data Tree = Branch Sort [Tree]
| Leaf Sort String deriving (Eq, Show)
nouns :: [String]
nouns = ["flight", "breeze", "trip", "morning"]
oneOf :: [String] -> Parser String
oneOf l = do
cs <- token identifier
guard (elem cs l)
return cs
noun :: Parser Tree
noun = do
cs <- token identifier
let a = Leaf Noun cs
let b = parse (oneOf nouns) cs
let c = Leaf Noun []
if null b then return c else return a
-- Parsing.hs
-- Functional parsing library from chapter 13 of Programming in Haskell,
-- Graham Hutton, Cambridge University Press, 2016.
module Parsing (module Parsing, module Control.Applicative) where
import Control.Applicative
import Data.Char
-- Basic definitions
newtype Parser a = P (String -> [(a,String)])
parse :: Parser a -> String -> [(a,String)]
parse (P p) inp = p inp
item :: Parser Char
item = P (\inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)])
-- Sequencing parsers
instance Functor Parser where
-- fmap :: (a -> b) -> Parser a -> Parser b
fmap g p = P (\inp -> case parse p inp of
[] -> []
[(v,out)] -> [(g v, out)])
instance Applicative Parser where
-- pure :: a -> Parser a
pure v = P (\inp -> [(v,inp)])
-- <*> :: Parser (a -> b) -> Parser a -> Parser b
pg <*> px = P (\inp -> case parse pg inp of
[] -> []
[(g,out)] -> parse (fmap g px) out)
instance Monad Parser where
-- (>>=) :: Parser a -> (a -> Parser b) -> Parser b
p >>= f = P (\inp -> case parse p inp of
[] -> []
[(v,out)] -> parse (f v) out)
-- Making choices
instance Alternative Parser where
-- empty :: Parser a
empty = P (\inp -> [])
-- (<|>) :: Parser a -> Parser a -> Parser a
p <|> q = P (\inp -> case parse p inp of
[] -> parse q inp
[(v,out)] -> [(v,out)])
-- Derived primitives
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
if p x then return x else empty
digit :: Parser Char
digit = sat isDigit
lower :: Parser Char
lower = sat isLower
upper :: Parser Char
upper = sat isUpper
letter :: Parser Char
letter = sat isAlpha
alphanum :: Parser Char
alphanum = sat isAlphaNum
char :: Char -> Parser Char
char x = sat (== x)
string :: String -> Parser String
string [] = return []
string (x:xs) = do char x
string xs
return (x:xs)
ident :: Parser String
ident = do x <- lower
xs <- many alphanum
return (x:xs)
nat :: Parser Int
nat = do xs <- some digit
return (read xs)
int :: Parser Int
int = do char '-'
n <- nat
return (-n)
<|> nat
-- Handling spacing
space :: Parser ()
space = do many (sat isSpace)
return ()
token :: Parser a -> Parser a
token p = do space
v <- p
space
return v
identifier :: Parser String
identifier = token ident
natural :: Parser Int
natural = token nat
integer :: Parser Int
integer = token int
symbol :: String -> Parser String
symbol xs = token (string xs)
Found the solution thanks to chi:
noun :: Parser Tree
noun = do
cs <- token identifier
guard (elem cs nouns)
let a = Leaf Noun cs
return a

Why does this loops with 'data' but not 'newtype'?

Here is the code :
import Control.Applicative
-- newtype Parser a = Parser { runParser :: String -> [(a, String)] }
data Parser a = Parser { runParser :: String -> [(a, String)] }
instance Functor Parser where
fmap f (Parser p) = Parser (\s -> [(f x, s') | (x, s') <- p s ] )
instance Applicative Parser where
pure a = Parser (\s -> [(a, s)])
Parser q <*> Parser p = Parser (\s -> [(f x, s'') | (f, s') <- q s, (x, s'') <- p s'])
instance Alternative Parser where
empty = Parser (\s -> [])
Parser q <|> Parser p = Parser (\s -> q s ++ p s)
item = Parser (\s -> case s of
(x:xs) -> [(x, xs)]
_ -> []
)
With the current code, runParser (some item) "abcd" loops, but if Parser is declared as newtype, it works just fine.
This is a great way of getting at one of the difference between data and newtype. The heart of the problem here is actually in the pattern matching of the <|> definition.
instance Alternative Parser where
empty = Parser (\s -> [])
Parser q <|> Parser p = Parser (\s -> q s ++ p s)
Remember that at runtime, a newtype becomes the same thing as the type it is wrapping. Then, when a newtype is pattern matched, GHC doesn't do anything - there is no constructor to evaluate to WNHF.
On the contrary, when a data is matched, seeing the pattern Parser q tells GHC it needs to evaluate that parser to WNHF. That is a problem, because some is an infinite fold of <|>. There are two ways to solve the problem with data:
Don't have Parser patterns in <|>:
instance Alternative Parser where
empty = Parser (\s -> [])
q <|> p = Parser (\s -> runParser q s ++ runParser p s)
Use lazy patterns:
instance Alternative Parser where
empty = Parser (\s -> [])
~(Parser q) <|> ~(Parser p) = Parser (\s -> q s ++ p s)

Sequencing basic parsers in Haskell and Frege using do notation

I try to run snippets from chapter 8 about functional parsers in Graham Hutton's 'Programming in Haskell' both in ghci and frege-repl.
I'm not able to sequence parsers using do syntax.
I have following definitions in Frege (Haskell version differs only with simpler item definition that doesn't pack and unpack String and Char and is the same as in the book):
module Parser where
type Parser a = String -> [(a, String)]
return :: a -> Parser a
return v = \inp -> [(v, inp)]
-- this is Frege version
item :: Parser Char
item = \inp ->
let inp' = unpacked inp
in
case inp' of
[] -> []
(x:xs) -> [(x,packed xs)]
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
-- sequencing
(>>=) :: 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 <- Parser.item
Parser.item
y <- Parser.item
Parser.return (x,y)
-- this works
p' :: Parser (Char, Char)
p' = item Parser.>>= \x ->
item Parser.>>= \_ ->
item Parser.>>= \y ->
Parser.return (x,y)
p' works both in ghci and frege-repl. However, when trying loading module I got those messages. First from ghci:
src/Parser.hs:38: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: Parser.return (x, y)
In the expression:
do { x <- item;
item;
y <- item;
Parser.return (x, y) }
Failed, modules loaded: none.
frege-repl is even less friendly because it simply kicks me out from repl with an error stack trace:
Exception in thread "main" frege.runtime.Undefined: returnTypeN: too many arguments
at frege.prelude.PreludeBase.error(PreludeBase.java:18011)
at frege.compiler.Utilities.returnTypeN(Utilities.java:1937)
at frege.compiler.Utilities.returnTypeN(Utilities.java:1928)
at frege.compiler.GenJava7$80.eval(GenJava7.java:11387)
at frege.compiler.GenJava7$80.eval(GenJava7.java:11327)
at frege.runtime.Fun1$1.eval(Fun1.java:63)
at frege.runtime.Delayed.call(Delayed.java:198)
at frege.runtime.Delayed.forced(Delayed.java:267)
at frege.compiler.GenJava7$78.eval(GenJava7.java:11275)
at frege.compiler.GenJava7$78.eval(GenJava7.java:11272)
at frege.runtime.Fun1$1.eval(Fun1.java:63)
at frege.runtime.Delayed.call(Delayed.java:200)
at frege.runtime.Delayed.forced(Delayed.java:267)
at frege.control.monad.State$IMonad_State$4.eval(State.java:1900)
at frege.control.monad.State$IMonad_State$4.eval(State.java:1897)
at frege.runtime.Fun1$1.eval(Fun1.java:63)
at frege.runtime.Delayed.call(Delayed.java:198)
at frege.runtime.Delayed.forced(Delayed.java:267)
at frege.control.monad.State$IMonad_State$4.eval
...
My intuition is that I need something apart >>= and return or there is something I should tell compilers. Or maybe I need to put p definition into State monad?
This is because String -> a is the monad that is being used in your do notation, since one of the instances of Monad in the Prelude is the function arrow.
Therefore, for example, the x in x <- Parser.item is an argument of type [(Char, String)].
You can get around this by making Parser a newtype and defining your own custom Monad instance for it.
The following works with Frege (and should work the same way with GHC language extension RebindableSyntax):
module P
where
type Parser a = String -> [(a, String)]
return :: a -> Parser a
return v = \inp -> [(v, inp)]
-- this is Frege version
item :: Parser Char
item = maybeToList . uncons
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
-- sequencing
(>>=) :: 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)
main = println (p "Frege is cool")
It prints:
[(('F', 'r'), "ege is cool")]
The main difference to your version is a more efficient item function, but, as I said before, this is not the reason for the stack trace. And there was this small indentation problem with the do in your code.
So yes, you can use the do notation here, though some would call it "abuse".

Haskell Parser fmap clarification

I have trouble in understanding the following fmap instance.Can someone explain me what fmap do(in this case) and how it can be used? Or write it less obfuscated?
Thanks!
newtype Parser a = P { getParser :: String -> Maybe (a, String) }
instance Functor Parser where
fmap f (P p) = P $ \s -> fmap (applyToFirst f) $ p s
{-|
Applies a function to the first component of a pair.
-}
applyToFirst :: (a -> b) -> (a, c) -> (b, c)
applyToFirst f (x, y) = (f x, y)
What does it do?
It transforms a parser X into parser Y, where Y does the following: runs parser X and applies function f to first element of parsing result pair.
How to use it?
p1 :: Parser String
p1 = P (\s -> Just ("foo", "bar"))
p2 :: Parser String
p2 = fmap (\s -> s ++ s) p1
Now (getParser p2) "whatever" equals Just ("foofoo", "bar").
Could it be less obfuscated?
It is not obfuscated actually. Haskell takes time to get used to.

Resources