haskellmonad-transformershaskeline

Using mtl's MonadReader with haskeline has type error


I want use InputT (ReaderT Int IO) a with MonadReader Int.

I write below code to make instance MonadReader on InputT

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
module HaskelineMonadReader where

import Control.Monad.Reader
import System.Console.Haskeline

instance MonadReader r m => MonadReader r (InputT m) where
    ask = lift ask
    local = mapInputT . local

main :: IO ()
main = putStrLn "HI"

But I get this type error.

HaskelineMonadReader.hs:11:13:
Couldn't match type ‘m0 a0 -> m0 a0’ with ‘forall b. m b -> m b’
Expected type: (m0 a0 -> m0 a0) -> InputT m a -> InputT m a
  Actual type: (forall b. m b -> m b) -> InputT m a -> InputT m a
Relevant bindings include
  local :: (r -> r) -> InputT m a -> InputT m a
    (bound at HaskelineMonadReader.hs:11:5)
In the first argument of ‘(.)’, namely ‘mapInputT’
In the expression: mapInputT . local

How can I fix this error.

Full source code is here


Solution

  • This compiles:

    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE UndecidableInstances #-}
    module HaskelineMonadReader where
    
    import Control.Monad.Reader
    import System.Console.Haskeline
    
    instance MonadReader r m => MonadReader r (InputT m) where
        ask = lift ask
        local f = mapInputT (local f)
    
    main :: IO ()
    main = putStrLn "HI"
    

    Update

    Here is the error message:

    Couldn't match type ‘m0 a0 -> m0 a0’
                   with ‘forall b. m b -> m b’
    
    Expected type: (m0 a0 -> m0 a0)       -> InputT m a -> InputT m a
    Actual type:   (forall b. m b -> m b) -> InputT m a -> InputT m a
    

    So it appears that the expected type is more general because the m0 does not have to be the same as m. In the actual type the m in m b must be the same as the m in m a.