是否有ReaderT被提升为monad



我已经编写了以下monad转换器(我认为它们彼此等效(,即:

newtype MonadReaderT1 r m a = MonadReaderT (ReaderT (r m) m a)
newtype MonadReaderT2 r m a = MonadReaderT (ReaderT (m r) m a)

这样做的目的是,我基本上想要一个ReaderT,但我的环境必须在Monad内部访问,它实际上不是一个固定的纯值(在我的情况下,它是一个需要定期刷新的身份验证令牌(。

我之所以认为MonadReaderT1MonadReaderT2是等价的,因为我可以去:

newtype B m = B (m A)

MonadReaderT1 BMonadReaderT2 A相同。

但我认为我需要这台额外的机器,而不仅仅是普通的旧ReaderT

但我觉得我不是第一个这样做或需要这样做的人。我刚刚重新发明了一种现有的类型吗?如果是,那是什么?

在这种情况下,我不确定是否值得定义一个单独的转换器。考虑一下,如果您使用带有Int环境的读取器转换器,您可能不会觉得有必要为这种情况编写一个特殊的转换器:

newtype IntReaderT m a = IntReaderT (ReaderT Int m a)

相反,您可以直接使用ReaderT Int

类似地,如果您碰巧想要一个monad操作作为您的环境,我认为您应该直接使用ReaderT,将您的monad堆栈定义为以下类型之一:

type M = ReaderT (IO Token) IO

或者一种新类型:

newtype M a = M { unM :: ReaderT (IO Token) IO a }

以及一个获取令牌的助手:

token :: M Token
token = ask >>= liftIO

如果您喜欢使用大量使用mtl约束的样式进行编写,则可以使用类和实例定义token

class MonadToken token m where
token :: m token
instance MonadToken Token M where
token = ask >>= liftIO

它允许您使用一元操作编写通用令牌:

authorized :: (MonadToken token m) => m Bool
authorized = do
t <- token
...

而实际上不必定义新的变压器。

相关内容

  • 没有找到相关文章

最新更新