What is the difference between liftM and mapM in Haskell

Luke picture Luke · May 2, 2011 · Viewed 8.6k times · Source

What is the difference between the functions liftM and mapM?

Answer

mgiuca picture mgiuca · May 2, 2011

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.