What is the difference between the functions liftM and mapM?

- 137,316
- 36
- 365
- 468

- 5,771
- 12
- 55
- 77
-
@larsmans That question has nothing to do with mapM. – mgiuca May 02 '11 at 12:01
-
@mgiuca: you're right. Excuse me. I should read more carefully, I guess. – Fred Foo May 02 '11 at 12:02
4 Answers
They aren't really related. I'll try to explain what each of them does. I assume you have a basic understanding of what a monad is.
liftM :: Monad m => (a -> b) -> (m a -> m b)
lets you use an ordinary function in a monad. It takes a function a -> b
, and turns it into a function m a -> m b
, that does exactly the same thing as the original function, but does it in a monad. The resulting function doesn't "do" anything to the monad (it can't, because the original function didn't know it was in a monad). For example:
main :: IO ()
main = do
output <- liftM ("Hello, " ++) getLine
putStrLn output
The function ("Hello, " ++) :: String -> String
prepends "Hello, " to a string. Passing it to liftM
creates a function of type IO String -> IO String
-- now you have a function that works in the IO monad. It doesn't do any IO, but it can take an IO action as input, and produces an IO action as output. Therefore, I can pass getLine
as input, and it will call getLine
, prepend "Hello, " to the front of the result, and return that as an IO action.
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
is quite different; note that unlike liftM
, it takes a monadic function. For example, in the IO monad, it has type (a -> IO b) -> [a] -> IO [b]
. It is very much like the ordinary map
function, only it applies a monadic action to a list, and produces a result list wrapped in a monadic action. For example (a pretty bad one):
main2 :: IO ()
main2 = do
output <- mapM (putStrLn . show) [1, 2, 3]
putStrLn (show output)
This prints:
1
2
3
[(),(),()]
What it is doing is iterating over the list, applying (putStrLn . show)
to each element in the list (having the IO effect of printing out each of the numbers), and also transforming the numbers into the ()
value. The resulting list consists of [(), (), ()]
-- the output of putStrLn
.

- 20,958
- 7
- 54
- 70
-
6Additionally, if you only care about the monadic effects of `mapM`, and not about the returned list, you can use `mapM_`. The `mapM_` function has type `Monad m => (a -> m b) -> [a] -> m ()`, it is useful in the putStrLn example, where you're probably not interested in the list of units. – Tom Lokhorst May 02 '11 at 12:19
-
@Tom Lokhorst Yep, that's right. (I couldn't come up with a useful example where the result is important on the IO monad.) – mgiuca May 02 '11 at 12:21
-
-
2@Luke The `putStrLn :: String -> IO ()` returns a unit value (that is the `()`). Here's another example: `mapM (\x -> putStrLn (show x) >> return (x + 1)) [1, 2, 3]`. This returns a list of Ints instead of units. – Tom Lokhorst May 02 '11 at 12:38
First, the types differ:
liftM :: (Monad m) => (a -> b) -> m a -> m b
mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
liftM
lifts a function of type a -> b
to a monadic counterpart.
mapM
applies a function which yields a monadic value to a list of values, yielding list of results embedded in the monad.
Examples:
> liftM (map toUpper) getLine
Hallo
"HALLO"
> :t mapM return "monad"
mapM return "monad" :: (Monad m) => m [Char]
... note that map
and mapM
differ! E.g.
> map (x -> [x+1]) [1,2,3]
[[2],[3],[4]]
> mapM (x -> [x+1]) [1,2,3]
[[2,3,4]]

- 4,830
- 1
- 25
- 38
-
3Is it `(\x -> [x + 1])` in the lambda for map? I tried the syntax without backslash for x and I get `Pattern syntax in expression context: x -> [x + 1]`. I am a Haskell newbie so I might be missing something here. – xtreak Jun 27 '16 at 15:00
The other answers have already explained it well, so I will just point out that you will usually see fmap
used instead of liftM
in real Haskell code, as fmap
is just a more general version in the type class Functor
. As all well-behaved Monad
s should be instances of Functor
as well, they should be equivalent.
You may also see the operator <$>
used as a synonym for fmap
.
Also, mapM f = sequence . map f
, so you can think of it as turning a list of values into a list of actions, and then running the actions one after another, collecting the results in a list.

- 138,522
- 17
- 304
- 385
liftM
and mapM
are quite different, as you can see via their types and their implementation:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as = sequence (map f as)
liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1 = do { x1 <- m1; return (f x1) }
so while mapM
applies a monadic function to each element of a list, liftM
applies a function in a monadic setting.

- 137,316
- 36
- 365
- 468