I have written a parser using megaparsec for a very simple language consisting of integer literals and two unary operators "a" and "b":
data ValueExpr = OpA ValueExpr
| OpB ValueExpr
| Integer Integer
valueExpr :: Parser ValueExpr
valueExpr = makeExprParser valueTerm valueOperatorTable
valueTerm :: Parser ValueExpr
valueTerm = parenthesised valueExpr
<|> Integer <$> integerLiteral
integerLiteral :: Parser Integer
integerLiteral = -- omitted
valueOperatorTable :: [[Operator Parser ValueExpr]]
valueOperatorTable = [[unaryOp "a" AOp,
unaryOp "b" BOp]]
parenthesised :: Parser a -> Parser a
parenthesised = between (char '(') (char ')')
unaryOp :: Text -> (a -> a) -> Operator Parser a
unaryOp name f = Prefix (f <$ symbol name)
binaryOp :: Text -> (a -> a -> a) -> Operator Parser a
binaryOp name f = InfixL (f <$ symbol name)
However, it seems that this doesn't allow me to "chain" unary operators, i.e. when trying to parse "ab1", I'm met with "unexpected 'b'". Why is that?
This is briefly mentioned in the documentation for makeExprParser:
Unary operators of the same precedence can only occur once (i.e., --2 is not allowed if - is prefix negate). If you need to parse several prefix or postfix operators in a row, ... you can use this approach:
manyUnaryOp = foldr1 (.) <$> some singleUnaryOp
This is not done by default because in some cases allowing repeating prefix or postfix operators is not desirable.
In your specific example, something like the following ought to work:
valueOperatorTable :: [[Operator Parser ValueExpr]]
valueOperatorTable = [[Prefix unaryOps]]
unaryOps :: Parser (ValueExpr -> ValueExpr)
unaryOps = foldr1 (.) <$> some (OpA <$ symbol "a" <|> OpB <$ symbol "b")
Related
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
hi i'm new in using haskell.
i'm actually using ghci to compile this code:
module Expr where
import Control.Applicative
import System.Environment
data Expr = Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Lit Integer
eval :: Expr -> Integer
eval e = case e of
Add a b -> eval a + eval b
Sub a b -> eval a - eval b
Mul a b -> eval a * eval b
Lit n -> n
-- Nouveau datatype nécessaire pour les instances
data Parser r = Parser {parse :: String -> Maybe (r, String)}
-- Instances
instance Functor Parser where
fmap f (Parser p) = Parser $ \s -> case p s of
Just (a, s') -> Just (f a, s')
Nothing -> Nothing
instance Applicative Parser where
pure x = Parser $ \s -> Just (x, s)
Parser p1 <*> pp2 = Parser $ \s -> case p1 s of
Just (f, s') -> case parse pp2 s' of
Just (a, s'') -> Just (f a, s'')
Nothing -> Nothing
Nothing -> Nothing
instance Alternative Parser where
empty = Parser $ const Nothing
(Parser p1) <|> pp2 = Parser $ \s -> p1 s <|> parse pp2 s
-- Le reste est identique
runParser :: Parser a -> String -> Maybe a
runParser (Parser p) s = case p s of
Just (r, "") -> Just r
_ -> Nothing
check :: (Char -> Bool) -> Parser Char
check f = Parser $ \s -> case s of
(x:xs) | f x -> Just (x, xs)
_ -> Nothing
char :: Char -> Parser Char
char c = check (== c)
oneOf :: [Char] -> Parser Char
oneOf cs = check (\c -> elem c cs)
number :: Parser Integer
number = read <$> some digit
where digit = oneOf "0123456789"
expr :: Parser Expr
expr = add_sub
where
add_sub = binOp Add '+' mul <|> binOp Sub '-' mul <|> mul
mul = binOp Mul '*' factor <|> factor
factor = parens <|> lit
lit = Lit <$> number
parens = char '(' *> expr <* char ')'
binOp c o p = c <$> p <*> (char o *> p)
evalExpr :: String -> Maybe Integer
evalExpr s = (fmap eval) $ runParser expr $ concat $ words s
what i'm trying to do is to create a Main to compile and run this code by myself and i'm struggling to do so.
so far i manage to understand and i would like to have something that is structurated like this:
module Main where
import System.Environment
import Expr
main :: IO ()
main = do
args <- getArgs
case args of
[] -> putStrLn "No argument"
[s]-> evalExpr args
i want to know if i can use ghci to generate a main or if there is another solution to create one
You already know that you need to create a constant called main whose type is IO ().
Let's start at your compilation errors. These are coming up because you have indented the contents of you main action less than the do keyword. Because Haskell is whitespace-sensitive, this is confusing the compiler. So your example above should actually look like this:
main :: IO ()
main = do args <- getArgs
case args of [] -> putStrLn "No argument"
[s] -> evalExpr args
I can't tell you whether this is actually what you want in your main action because I don't know what you want it to do, but it will probably look similar to what you're running in GHCi.
For example, if your GHCi session looks like this:
Prelude> let x = foo bar
Prelude> print x
the equivalent main would look like this:
main :: IO ()
main = do let x = foo bar
print x
Assuming you've created a project using cabal or stack, then your Expr module should be in src/Expr.hs and your Main module should be in src/Main.hs or app/Main.hs. The code you have looks at first glance like it should compile and run fine.
You can then either run a REPL instance (cabal repl or stack repl) in your project directory and call the main function from there or you can run it as an executable (cabal run or stack run) and pass in your arguments from the command-line.
If you haven't created a project using either of the tools I mentioned above, then this documentation should prove useful:
Cabal documentation
Stack documentation
Edit:
I had neglected to look at the code in detail before/try to compile & run it.
Your main function has some issues with the pattern match line of:
[s] -> evalExpr args
Since your evalExpr function takes a String you need to pass it something instead of args, which is of type [String].
Also, the result of evalExpr is of type Maybe Integer and needs to be of type IO () to end the case statement properly.
If you replace it with this:
_ -> putStrLn . show $ evalExpr (unwords args)
then running stack run 1 + 1 from the command-line will output Just 2.
To get this to run as a stand-alone executable, you'll have to run stack install which will create an executable on your system that you can run. On mine it outputs to ~/.local/bin/Expr-exe which I can then call:
paul#Pauls-MacBook-Pro Expr % ~/.local/bin/Expr-exe 1 + 1
Just 2
(side note: stack install is apparently a short-cut for stack build --copy-bins)
I'm trying to implement my own Applicative parser, here's the code I use:
{-# LANGUAGE ApplicativeDo, LambdaCase #-}
module Parser where
-- Implementation of an Applicative Parser
import Data.Char
import Control.Applicative (some, many, empty, (<*>), (<$>), (<|>), Alternative)
data Parser a = Parser { runParser :: String -> [(a, String)] }
instance Functor Parser where
-- fmap :: (a -> b) -> (Parser a -> Parser b)
fmap f (Parser p) = Parser (\s -> [(f a, s') | (a,s') <- p s])
instance Applicative Parser where
-- pure :: a -> Parser a
-- <*> :: Parser (a -> b) -> Parser a -> Parser b
pure x = Parser $ \s -> [(x, s)]
(Parser pf) <*> (Parser p) = Parser $ \s ->
[(f a, s'') | (f, s') <- pf s, (a, s'') <- p s']
instance Alternative Parser where
-- empty :: Parser a
-- <|> :: Parser a -> Parser a -> Parser a
empty = Parser $ \_s -> []
(Parser p1) <|> (Parser p2) = Parser $ \s ->
case p1 s of [] -> p2 s
xs -> xs
char :: Char -> Parser Char
char c = Parser $ \case (c':cs) | c == c' -> [(c,cs)] ; _ -> []
main = print $ runParser (some $ char 'A') "AAA"
When I run it, it gets stuck and never returns. After digging into the problem I pinpointed the root cause to be my implementation of the <|> method. If I use the following implementation then everything goes as expected:
instance Alternative Parser where
empty = Parser $ \_s -> []
p1 <|> p2 = Parser $ \s ->
case runParser p1 s of [] -> runParser p2 s
xs -> xs
These two implementations are, in my understanding, quite equivalent. What I guess is that this may have something to do with Haskell's lazy evaluation scheme. Can someone explain what's going on?
Fact "star": in your implementation of (<*>):
Parser p1 <*> Parser p2 = ...
...we must compute enough to know that both arguments are actually applications of the Parser constructor to something before we may proceed to the right-hand side of the equation.
Fact "pipe strict": in this implementation:
Parser p1 <|> Parser p2 = ...
...we must compute enough to know that both parsers are actually applications of the Parser constructor to something before we may proceed to the right-hand side of the equals sign.
Fact "pipe lazy": in this implementation:
p1 <|> p2 = Parser $ ...
...we may proceed to the right-hand side of the equals sign without doing any computation on p1 or p2.
This is important, because:
some v = some_v where
some_v = pure (:) <*> v <*> (some_v <|> pure [])
Let's take your first implementation, the one about which we know the "pipe strict" fact. We want to know if some_v is an application of Parser to something. Thanks to fact "star", we must therefore know whether pure (:), v, and some_v <|> pure [] are applications of Parser to something. To know this last one, by fact "pipe strict", we must know whether some_v and pure [] are applications of Parser to something. Whoops! We just showed that to know whether some_v is an application of Parser to something, we need to know whether some_v is an application of Parser to something -- an infinite loop!
On the other hand, with your second implementation, to check whether some_v is a Parser _, we still must check pure (:), v, and some_v <|> pure [], but thanks to fact "pipe lazy", that's all we need to check -- we can be confident that some_v <|> pure [] is a Parser _ without first checking recursively that some_v and pure [] are.
(And next, you will learn about newtype -- and be confused yet again when changing from data to newtype makes both implementation work!)
I need to write a code that evaluates a string of operations and outputs the resulting integer of that string. I wrote something but it's not working and would like some help. I need to use fold since it is easier but I'm sure what's wrong. This is on Haskell and using Emacs.
evalExpr :: String -> Int
evalExpr xs = foldl 0 xs where
f v x | x == "+" = (+) v
| x == "-" = (-) v
| x == " " = 0
| otherwise = read v :: Int
For example:
evalExpr "2+4+5-8"
the output should be: 3
evalExpr ""
the output should be: 0
This is because it should read the string left to right.
You can do as #5ndG suggested. However, to evaluate a string of operations, using parsec is a better way. Here is an example for your case:
module EvalExpr where
-- You need parsec to do parsing work, and the following are just example
-- modes for your simple case.
import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.String
-- A data structure for your simple arithmetic expresssion
data Expr = Lit Int
| Plus Expr Expr
| Minus Expr Expr
deriving Show
-- Evaluate an Expr to an integer number
eval :: Expr -> Int
eval (Lit n) = n
eval (Plus e1 e2) = eval e1 + eval e2
eval (Minus e1 e2) = eval e1 - eval e2
-- The following do the parsing work
-- Parser for an integer number
int :: Parser Expr
int = Lit . read <$> (many1 digit <* spaces) -- A number may be followed by spaces
-- Parser for operators "Plus" and "Minus"
plus, minus :: Parser (Expr -> Expr -> Expr)
plus = Plus <$ char '+' <* spaces
minus = Minus <$ char '-' <* spaces
-- Parser for Expr
expr :: Parser Expr
expr = chainl int (plus <|> minus) (Lit 0)
-- Evalute string to an integer
evalExpr :: String -> Int
evalExpr s = case parse expr "" s of
Left err -> error $ show err
Right e -> eval e
The above is just an simple example of using parsec. If your actual case is more complex, you'll need more work to do. So learning to use parsec is necessary. The intro_to_parsing is a good start. Also in the package description are there some learning resources.
By the way, Text.Parsec.Expr in parsec can parse an expression more conveniently, but above all, you need to know the basic of parsec.
Happy learning!
You're not far off something that works on your examples. Try this:
evalExpr :: String -> Int
evalExpr xs = foldl f (0 +) xs 0
f :: (Int -> Int) -> Char -> (Int -> Int)
f v ch | ch == '+' = (v 0 +)
| ch == '-' = (v 0 -)
| ch == ' ' = v
| otherwise = (v (read [ch] :: Int) +)
So the main difference to yours is that the accumulator in the fold is a function that takes in one Int and produces one Int, instead of just being an Int.
I am going through Write Yourself a Scheme in Haskell. Its a great tutorial, but I've run into a wall with one of the parsing exercises:
parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit
Rewrite parseNumber using:
Do-notation
explicit sequencing with the >>= operator
I had no problems with do-notation:
parseNumber :: Parser LispVal
parseNumber = do x <- many1 digit
let y = read x
return $ Number y
For #2 I've tried a bunch of variations such as:
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (liftM (Number . read))
but I keep running into type errors. I have two questions.
Why am I getting type errors? Am I misunderstanding the monadic bind operator?
Why AREN'T I getting similar type errors with my do-notation solution?
I feel like I am missing a fundamental concept regarding types?
You're attempting a non-trivial transformation from do-notation to bind notation, I recommend doing it the "trivial" way, and then making it points-free.
Recall:
x <- m === m >>= \x ->
let x = e === let x = e in
Then you have:
parseNumber = many1 digit >>= \x ->
let y = read x in
return (Number y)
(I've removed the $ to avoid precedence problems.)
We can then convert this into:
parseNumber = many1 digit >>= \x -> return (Number (read x))
= many1 digit >>= return . Number . read
Now, if you want to use liftM, you need to stop using bind, since the lifted function expects a monadic value as its argument.
parseNumber = liftM (Number . read) (many1 digit)
In your case, bind has type:
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(since you're using Parser as the Monad)
You give bind two arguments: the first one, many1 digit, should be ok (regarding the type); but the type of the second argument is the result type of liftM, namely Parser a -> Parser b and this does not fit the second argument's expected type (a -> Parser b)!
Without having tested it: instead of using liftM (Number.read) as second argument of bind, try using return . Number . read - this should have the right type and gives probably what you want...