I have the following code snippet from internet:
calculateLength :: LengthMonad Int
calculateLength = do
-- all the IO operations have to be lifted to the IO monad in the monad stack
liftIO $ putStrLn "Please enter a non-empty string: "
s <- liftIO getLine
if null s
then throwError "The string was empty!"
else return $ length s
and could not understand, why the author use liftIO
?
What is the purpose of liftIO
?
It is defined as follows:
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
Is it possible to lift IO a -> [a]
? It looks like natural transformation.
IO
operations like getLine, putStrLn "..."
only work inside the IO
monad. Using them inside any other monad will trigger a type error.
Still, there are many monads M
which are defined in terms of IO
(e.g. StateT Int IO
, and apparently your LengthMonad
as well) and because of that they allow IO
actions to be converted into M
-actions, and executed as such.
However, we need a conversion for each M
:
convertIOintoM1 :: IO a -> M1 a
convertIOintoM2 :: IO a -> M2 a
convertIOintoM3 :: IO a -> M3 a
...
Since this is cumbersome, the library defines a typeclass MonadIO
having such conversion function, so that all the functions above can be named liftIO
instead.
In practice, liftIO
is used each time one wants to run IO
actions in another monad, provided such monad allows for it.
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