How do I write this function using the >>= operator?
parseNumber2 :: Parser LispVal
parseNumber2 = do x <- many1 digit
return $ (Number . read) x
A straightforward desugaring of the do-notation gives
parseNumber2 :: Parser LispVal
parseNumber2 = many1 digit >>= (return . Number . read)
but the more idiomatic way is to use fmap or the equivalent <$> operator from Control.Applicative
parseNumber2 = Number . read <$> many1 digit
To desugar do-notation:
Flip any <- bindings over to the right side and add >>= and a lambda abstraction
do x <- a
y <- b
...
becomes
a >>= \x ->
b >>= \y ->
...
For any non-binding forms, add a >> on the right:
do a
b
...
becomes
a >>
b >>
...
Leave the last expression alone.
do a
becomes
a
Applying these rules to your code, we get
parseNumber2 =
many1 digit >>= \x ->
return $ (Number . read) x
Do some simplifications
parseNumber2 = many1 digit >>= \x -> (return . Number . read) x
parsenumber2 = many1 digit >>= (return . Number . read)
Now, for any monad, fmap or <$> can be defined as
f <$> x = x >>= (return . f)
Use this to get the idiomatic form
parseNumber2 = Number . read <$> many1 digit
Related
I'm trying to write a simple parser via Haskell, but stuck at an infinite loop.
the code is:
import Control.Applicative (Alternative, empty, many, (<|>))
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 x = Parser $ \s -> [(x, s)]
(Parser pf) <*> (Parser p) = Parser $ \s -> [(f' x, ss') | (f', ss) <- pf s, (x, ss') <- p ss]
instance Alternative Parser where
empty = Parser $ \s -> []
(Parser p1) <|> (Parser p2) = Parser $ \s ->
case p1 s of
[] -> p2 s
xs -> xs
singleSpaceParser :: Parser Char
singleSpaceParser = Parser $ \s ->
( case s of
x : xs -> if x == ' ' then [(' ', xs)] else []
[] -> []
)
multiSpaceParser :: Parser [Char]
multiSpaceParser = many singleSpaceParser
I just load this file in ghci, and run:
runParser multiSpaceParser " 123"
I expect it to get [(" ", "123")], but actually it got an infinite loop
I used trace to debug, and it seems that many is wrong
How can I fix this bug?
Let's assume
many p = (:) <$> p <*> many p <|> pure []
and consider the call
many singleSpaceParser " 123"
(The string does not actually matter here, the many singleSpaceParser call will always loop.)
One reduction step yields
((:) <$> singleSpaceParser <*> many singleSpaceParser <|> pure []) " 123"
Now observe that, in order to reduce the call to (<|>), we have to evaluate both arguments of (<|>) to be of the shape Parser ....
Let's consider doing that for (:) <$> singleSpaceParser <*> many singleSpaceParser. As both (<$>) and (<*>) are infixl 4, this is an application of <*> at the outermost level.
But now observe that in order to reduce (<*>), we again have to evaluate both arguments of (<*>) to be of the shape Parser ..., so in particular the recursive call many singleSpaceParser.
This is where we get the infinite loop.
By switching data to newtype (or alternatively, at least avoiding aggressively pattern-matching on the Parser constructor in all the second arguments), these problems can be avoided.
This is a general question inspired by a particular piece of code I wrote that I'm not happy with. I'm using Data.Binary.Get to grab some data from a binary file. Some of the code looks a bit like this
import Data.Binary.Get
data Thing = Thing
{
aaa :: Integer,
bbb :: Integer,
ccc :: Integer
} deriving (Show)
getThing :: Get Thing
getThing = do
laaa <- getWord8 >>= \x -> return (toInteger x)
lbbb <- getWord16host >>= \x -> return (toInteger x)
lccc <- getWord32host >>= \x -> return (toInteger x)
return $ Thing laaa lbbb lccc
The "getThing" function is really long. I am hoping there is a nice way to do something like the following pseudocode or maybe something even more concise.
[laaa, lbbb, lccc] <- MAGIC [getword8, getword16, getWord32] >>= \x -> return (toInteger x)
What have you got?
I would write
getThing :: Get Thing
getThing = Thing <$> intFrom getWord8 <*> intFrom getWord16 <*> intFrom getWord32
where
where intFrom x = toInteger <$> x
The magic you are looking for is known as sequence, but you can't put IO Word8, IO Word16 and IO Word32 in the same list:
getThing :: Get Thing
getThing = do
[laaa, lbbb, lccc] <- sequence [toInteger <$> getword8, toInteger <$> getword16, toInteger <$> getWord32]
return $ Thing laaa lbbb lccc
According to the documentation <$> is an synonym for fmap and they have the following types:
(<$>) :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> f a -> f b
So it seems to me, from the signatures above, that they take the arguments in the same order, the only difference being that one is infix and the other is not. I have two pieces of code, one using fmap, and the other using <$>. Why is it that only the former runs correctly?
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . words <$> getLine
putStrLn $ show (x + y)
This one won't compile:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . fmap words getLine
putStrLn $ show (x + y)
Precedence of operators is expressed as an integer between 0 and 9, while function application effectively has precedence 10 (higher than any operator).
(.) has very high precedence (9), while (<$>) has lower precedence (4), resulting in your first expression being parsed as
((map read) . words) <$> getLine
while your second expression is parsed as
(map read) . (fmap words getLine)
resulting in an attempt to compose an IO [String] value with a function of type [String] -> [a].
This is due to operator precedence. If we look at the source code, we see that:
infixl 4 <$>
infixr 9 .
So that means that if you write:
map read . words <$> getLine
Haskell sees this as:
(map read . words) <$> getLine
But if you write:
map read . fmap words getLine
Haskell sees this as:
(map read) . (fmap words getLine)
So the arguments of fmap are different.
If we however add brackets, the two will be equivalent:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . (words <$> getLine)
putStrLn $ show (x + y)
I'm just starting to learn Haskell from this wikibook and I had a little trouble with one of the exercises.
Specifically, the following doesn't work as I expect
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (return $ Number . read)
unless I change it slightly
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (\n -> return $ Number . read $ n)
I was hoping someone could explain why return $ Number . read doesn't evaluate to the same lambda function that I explicitly created in the second definition, since I thought that this is exactly what partial function evaluation does when it's used in point free style code (obviously not!)
Thanks for any help, hopefully it's not another beginner’s monad problem...
This is just an issue of how $ associates. Fundamentally, $ is just an operator for writing fewer parentheses; it's the same as adding parentheses wrapping to the end of the expression.
Using this idea, we can rewrite your second example:
parseNumber = (many1 digit) >>= (\n -> return (Number . read ( n)))
For reference, the original expression with parentheses looks like this:
parseNumber = (many1 digit) >>= (return (Number . read))
So the equivalent of the partial application is actually:
parseNumber = (many1 digit) >>= (\n -> (return (Number . read)) n)
Basically, combining multiple $ associates differently than what you expected.
Go to the definitions --
($) :: (a -> b) -> a -> b
($) = id
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f g x = f (g x)
Now you have
return $ Number . read = ($) return (Number . read) -- (.) has higher precedence
= return (Number . read)
and the monad you're in is the Parser monad, so this is trying to bind a parsed value to a function that returns a parser for another function (many layers of abstraction!)
Instead, what you want is
return . Number . read
which is equivalent to what you wrote, as you can see by doing
\n -> return $ Number . read $ n = \n -> return . Number . read $ n -- definition of (.)
= return . Number . read -- eta reduction
Finally, note that when you see the pattern
x >>= return . f
this can always be replaced with
fmap f x -- or liftM f x
i.e. it shows that you're not really using the Monad instance at all, but instead the weaker (and more general) Functor instance.
It looks like you want:
parseNumber = (many1 digit) >>= (return . Number . read)
or alteratively
parseNumber = (many1 digit) `fmap` (Number . read)
Number . read is a function String -> LispVal so the type of return $ Number . read is Parser (String -> LispVal), while you need the function to have type String -> Parser LispVal
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...