
On Fri, 4 Feb 2011, Anders Kaseorg wrote:
but isn’t M isomorphic to ReaderT () IO (via unM :: M a -> ReaderT () IO a, M . mapReaderT liftIO :: IO a -> M a)?
Er, M . mapReaderT liftIO :: ReaderT () IO a -> M a. Of course that doesn’t actually type check until you eta-expand it: (\x -> M (mapReaderT liftIO x)) :: ReaderT () IO a -> M a. Just to demonstrate that I didn’t use the triviality of ReaderT (), here’s a less trivial example with ReaderT and StateT: data M a = M { unM :: forall m. MonadPeelIO m => ReaderT Int (StateT Char m) a } instance Monad M return x = M (return x) M mx >>= fxmy = M (mx >>= unM . fxmy) instance MonadIO M where liftIO io = M (liftIO io) -- M ≅ ReaderT Int (StateT Char IO) fromM :: M a -> ReaderT Int (StateT Char IO) a fromM = unM toM :: ReaderT Int (StateT Char IO) a -> M a toM mx = M (mapReaderT (mapStateT liftIO) mx) instance MonadPeelIO M where peelIO = toM (liftM (\k (M mx) -> liftM toM (k mx)) peelIO) Anders