如果你只是想隐藏
MonadIO
-您的
AppM
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
并更改
data
newtype App a = App {runApp :: ReaderT Env (LoggingT IO) a}
deriving (Functor, Applicative, Monad, MonadReader Env,
, MonadLoggerIO }
因此
App
是不是
如果你需要的话
liftIO
就像你可以在你的库中提供的动作一样
putStrLn :: String -> App ()
putStrLn = fmap App . liftIO Prelude.putStrLn
注:the
是用于
ReaderT Env (LoggingT IO) ()
然后将其包裹在
,并且不公开完整的IO功能。
使现代化
关于如何实施的问题
Functor
,
Applicative
和
Monad
这仅仅是包装/展开的任务:
instance Functor App where
fmap f = App . fmap f . runApp
instance Applicative App where
pure = App . pure
mf <*> mx = App (runApp mf <*> runApp mx)
instance Monad App where
mx >>= f = App $ (runApp mx) >>= (runApp . f)
>>= :: ReaderT Env (LoggingT IO) a -> (a -> ReaderT Env (LoggingT IO) b) -> ReaderT Env (LoggingT IO) b
但是
mx :: App a
和
f :: a -> App b
所以我们需要
runApp :: App a -> ReaderT Env (LoggingT IO) a
f
在未包装的环境下工作——这在写下来时看起来很明显,但在此之前可能会引起一些头痛。
更新2
我发现有人把我和monad阅读器联系了很久(但在同一个星系)
Ed Z. Yang -
Three Monads (Logic, Prompt, Failure)