Haskell: Why is this monad transformation wrong?

Viewed 280

I am studying monad transformers, and I read this SO post about how to avoid lifts.

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
1 Answers
Related