with lists
I was trying to remember how to use Haskell. This blog post focuses only on Control.Monad.liftM
function.
The type of liftM
is (Monad m) => (a1 -> r) -> m a1 -> m r
which evaluates the second argument with the first argument as if it's in do block.
Let me explain that with the following example. You need the list of the values which each of them are three times bigger than the original list [1, 2, 3]. The most straightforward way in Haskell is to use list comprehension.
[ x * 3 | x <- [1, 2, 3]]
List Comprehension is just a syntactic sugar of List Monad. The code is equivalent to the following code.
do x <- [1, 2, 3]
return $ x * 3
Do notation is just a syntactic sugar of List Monad as well.
[1, 2, 3] >>= \x -> return (x * 3)
You also can make the code simpler with point free style.
[1, 2, 3] >>= return . (* 3)
Now it's time to use liftM
. You can write the code with liftM
in the following way.
liftM (* 3) [1, 2, 3]
This is the simplest. Note that you have to declare import Control.Monad
to use liftM
.
with Parsec
The code below is from Write Yourself a Scheme in 48 Hours.
parseNumber = liftM (Number . read) $ many1 digit
I rewrite it without liftM
.
parseNumber = do x <- many1 digit
return $ Number $ read x
or
parseNumber = do x <- many1 digit
return $ (Number . read) x
or
parseNumber = many1 digit >>= \x -> return $ (Number . read) x
or
parseNumber = many1 digit >>= \x -> (return . Number . read) x
or
parseNumber = many1 digit >>= return $ Number . read
summary
Using liftM
can make code simpler and easier to understand with its natural order of arguments.
The most difficult thing for using liftM
is to write the correct spelling of liftM
. I cannot remember how many times I wrote listM
instead of liftM
. It is very difficult and fatal issue.
Hi, I found this page while trying to understand liftM via the same tutorial. Thanks for your page, I found it very helpful.
ReplyDeleteBut I think perhaps the last example has an error - it doesn't compile as-is. I believe it should read "parseNumber = many1 digit >>= return . Number . read".
Cheers,
John :^P
Oh right, thanks for pointing it out!
ReplyDelete