gpt4 book ai didi

haskell - 如何创建一个允许 IO 但不是 MonadIO 的 monad?

转载 作者:行者123 更新时间:2023-12-02 21:28:42 28 4
gpt4 key购买 nike

我正在尝试创建一个仅允许特定 IO 函数的 monad。这意味着这个假设的 monad 不能是 MonadIO 并且不能允许调用 liftIO

这是我到目前为止所拥有的,但我一直使用 AppMMonad 实例:

data AppM a = AppM {unwrapAppM :: ReaderT Env (LoggingT IO) a}

instance Functor AppM where
fmap fn appm = AppM $ fmap fn (unwrapAppM appm)


instance Applicative AppM where
pure a = AppM $ pure a

最佳答案

如果您只是想隐藏 AppMMonadIO 特性

我会继续输入

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

并将data声明更改为

newtype App a = App {runApp :: ReaderT Env (LoggingT IO) a}
deriving (Functor, Applicative, Monad, MonadReader Env,
, MonadLoggerIO }

因此,如果您需要像 liftIO 这样的操作,您的 App 就不是 MonadIO,您可以在库中提供这些操作,例如

putStrLn :: String -> App ()
putStrLn = fmap App . liftIO Prelude.putStrLn

注意:liftIO 用于 ReaderT Env (LoggingT IO) (),然后将其包装到 App 中,并且您不会公开完整的 IO 功能。

更新

关于如何实现FunctorApplicativeMonad的问题,它只是包装/展开的任务:

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 af::a -> App b 所以我们需要

runApp :: App a -> ReaderT Env (LoggingT IO) a

解包 f 的结果类型以在解包设置中工作 - 这在写下来时似乎非常明显,但在此之前可能会引起一些头痛。

更新2

我发现有人从 monad reader Ed Z. Yang - Three Monads (Logic, Prompt, Failure) 链接了我很长一段时间(但在同一个星系)的论文。

关于haskell - 如何创建一个允许 IO 但不是 MonadIO 的 monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45266054/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com