Haskell 合并ReaderT单子?
能够组合不同的ReaderT环境似乎很有用 例如,通用日志记录工具可能如下所示:Haskell 合并ReaderT单子?,haskell,monads,Haskell,Monads,能够组合不同的ReaderT环境似乎很有用 例如,通用日志记录工具可能如下所示: logit :: Text -> ReaderT Bool IO () logit str = do debugflag <- ask liftIO $ if debugflag then putStrLn ("debug: " ++ str) else return () 因此,我可以在同一个函数中同时使用foo和logit。您希望将它们分层到一个堆叠的monad中,
logit :: Text -> ReaderT Bool IO ()
logit str = do debugflag <- ask
liftIO $ if debugflag then putStrLn ("debug: " ++ str) else return ()
因此,我可以在同一个函数中同时使用
foo
和logit
。您希望将它们分层到一个堆叠的monad中,但它们不能堆叠在一起,因为它们都声明IO
正是包装的monad。幸运的是,您的代码已经足够通用,可以解除此限制。最通用的函数类型使用MonadIO
,而不是专门使用IO
。如果将类型更改为
logit :: MonadIO m => Text -> ReaderT Bool m ()
foo :: MonadIO m => ReaderT Text m ()
然后,liftIO
调用将整个堆栈中的IO
操作提升到底部的IO
monad
需要说明的是,您编写的类型不需要使用liftIO
——相同的类型只需lift
,但由于IO
是MonadIO
的一个实例,因此您的(过度)专用类型也将通过检查。请检查
logit :: MonadIO m => Text -> ReaderT Bool m ()
foo :: MonadIO m => ReaderT Text m ()