I am studying monad transformers, and I read this SO post about how to avoid lift
s.
My thought was that MonadIO
are monads in which IO
can be embedded, and MonadWriter w
are monads in which WriterT w
can be embedded. So I wrote the code below (read, accumulate and record numbers until we get a zero), where a working version using explicit lift
is in comments. But GHC complains. What am I doing wrong?
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.IO.Class
import Control.Monad.Writer.Class (MonadWriter)
import Control.Monad.Trans.Reader
import Control.Monad.Trans.Writer
-- f :: ReaderT Int (WriterT [String] IO) Int
-- m1 = ReaderT, m2 = WriterT
f :: (MonadWriter [String] m1, MonadIO m2) => m1 (m2 (IO Int))
f = do
s <- liftIO getLine
tell ["Input: " ++ s] -- lift $ tell ["Input: " ++ s]
let i = read s :: Int
if i == 0
then ask
else local (+i) f
main = do
rst <- runWriterT $ runReaderT f 0
print rst