理解 Haskell 中的 RWST

Pis*_*tor 1 monads haskell functional-programming state-monad monad-transformers

我研究了这个,试图理解几个转换器单子如何相互作用,特别是更好地理解单子lift并与单子堆叠

对于这里找到的 RWST monad (我认为这是最好的文档),它是一个堆叠的 monad,其中 Reader、Writer、State 都是一个 Monadic 层(并且按照堆叠顺序)。或者说应该如何理解呢?当我查看定义时,runRWST :: r -> s -> m (a, s, w)我将其理解为将读取器环境作为状态环境并将任何单子包装在 的m返回值周围RWS。这也意味着这个monad中只存在两层monad。即外部 monadm和包含多个 monad 的元组。

这反过来也意味着您只能使用lift一次。将读取器状态单子中的值提升到外部单子中。

从这个意义上说get, 和ask只是应用两个内部单子之一的两个函数。对于最后一点,我仍然不确定我是否理解为什么即使阅读了这篇 stackoverflow 帖子,您仍然需要一个reader和一个state -monad 。我猜读者只对只读有意义,但如果不希望这样,可以在两个单独的状态单子周围使用变压器单子吗?

一个例子:

这些评论让我有理由思考并使以下内容更加明确......以下类型定义的内部单子和外部单子是什么?它本身是RWST一个包裹着(因此是外部单子)Either String(内部单子)的单子吗?

type MyRWST a = RWST
                 (String -> Either String MyType)       
                 [Int] 
                 (MyEnv, [String], [String])
                 (Either String)
                 a
Run Code Online (Sandbox Code Playgroud)

Sil*_*olo 9

monad转换器的内部 monad始终是类型参数。您提供的类型不是变压器。

type MyRWST a = RWST
                 (String -> Either String MyType)       
                 [Int] 
                 (MyEnv, [String], [String])
                 (Either String)
                 a
Run Code Online (Sandbox Code Playgroud)

这是一个Monad。将此与类似变压器进行比较MaybeT

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
Run Code Online (Sandbox Code Playgroud)

MaybeT接受两个类型参数,第一个本身接受一个参数,所以它的种类是(* -> *) -> * -> *。如果加上更明确的括号,那就是(* -> *) -> (* -> *). 现在我们可以明白为什么它被称为变压器了。它需要一个 monad(of kind * -> *)并将其转换为一个新的 monad(也是 of kind * -> *)。

RWST定义为

newtype RWST r w s m a = RWST { unRWST :: r -> s -> w -> m (a, s, w) }
Run Code Online (Sandbox Code Playgroud)

现在这需要很多类型参数,但是如果我们修复rws,我们就会得到一个转换器。也就是说,RWST本身不是一个 monad 转换器,但对于任何rw、 和sRWST r w s 一个转换器。完整的种类RWST

RWST :: * -> * -> * -> (* -> *) -> * -> *
Run Code Online (Sandbox Code Playgroud)

虽然您可以认为RWST具有三层(读取器、写入器和状态),但它实际上只有一层。的“下一层”RWST r w s m确实是m。因此,要直接回答您的问题lift, 的类型签名lift

lift :: (MonadTrans t, Monad m) => m a -> t m a
Run Code Online (Sandbox Code Playgroud)

当 时t ~ RWST r w s,我们得到

lift :: Monad m => m a -> RWST r w s m a
Run Code Online (Sandbox Code Playgroud)

因此,单曲lift带领我们克服了整个 RWST r w s混乱。