What is the difference between the functions liftM and mapM?
The core idea is that mapM maps an "action" (ie function of type a -> m b ) over a list and gives you all the results as a m [b] . mapM_ does the same thing, but never collects the results, returning a m () . If you care about the results of your a -> m b function (ie the b s), use mapM .
Lifting is a concept which allows you to transform a function into a corresponding function within another (usually more general) setting.
What is a Monad? A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With