理解 Haskell 中的 RWST

问题描述 投票:0回答:1

我查看了 this,试图了解几个 Transformer monad 是如何相互作用的,尤其是更好地理解

lift
stacking 与 monad。

对于here找到的RWST monad(我认为这是最好的文档),它是否是一个堆叠的monad,其中Reader,Writer,State每个都是一个monadic层(并且按照堆叠顺序)。或者说应该如何理解呢? 当我查看定义

runRWST :: r -> s -> m (a, s, w)
时,我将其理解为将读取器环境作为状态环境,并将任何 monad
m
包装在
RWS
的返回值周围。这也意味着这个monad中只存在两层monad。即,外部单子
m
,以及包含多个单子的元组。

这也意味着您只能使用

lift
一次。将值从 readerstate monad 提升到外部 monad。

从这个意义上说,

get
ask
只是应用两个内部单子之一的两个函数。对于最后一点,我仍然不确定为什么你需要一个 readerstate-monad,即使已经阅读了 this stackoverflow post。我猜 reader 仅对只读有意义,但如果不希望这样,可以在两个单独的 state-monad 周围使用转换器 monad 吗?

一个例子:

这些评论让我有理由思考并使以下内容更加明确......以下类型定义的内部单子和外部单子是什么?

RWST
本身是一个包裹着
Either String
(内部单子)的单子(因此是外部单子)吗?

type MyRWST a = RWST
                 (String -> Either String MyType)       
                 [Int] 
                 (MyEnv, [String], [String])
                 (Either String)
                 a
haskell functional-programming monads monad-transformers state-monad
1个回答
0
投票

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

type MyRWST a = RWST
                 (String -> Either String MyType)       
                 [Int] 
                 (MyEnv, [String], [String])
                 (Either String)
                 a

此类型有种类

* -> *
,这是一种奇特的说法,它只需要一个类型参数。[1] 将其与像
MaybeT
这样的转换器进行比较。

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

MaybeT
采用两个类型参数,第一个本身采用一个参数,因此其类型为
(* -> *) -> * -> *
。如果加上更明确的括号,那就是
(* -> *) -> (* -> *)
。现在我们可以明白为什么它被称为transformer了。它需要一个单子(
* -> *
类型)并将其转换为一个新的单子(也属于
* -> *
类型)。

RWST
定义为

newtype RWST r w s m a = RWST { unRWST :: r -> s -> w -> m (a, s, w) }

现在需要大量类型参数,但是如果我们修复r

w
s
,我们就会得到一个变压器。也就是说,
RWST
本身并不是一个monad转换器,但对于任何
r
w
s
来说,
RWST r w s
一个转换器。完整的 RWST

RWST :: * -> * -> * -> (* -> *) -> * -> *
虽然您可以

认为RWST

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

lift :: (MonadTrans t, Monad m) => m a -> t m a

t ~ RWST r w s

时,我们得到

lift :: Monad m => m a -> RWST r w s m a
因此,一个

lift

就让我们克服了
整个RWST r w s
的混乱。


[1] 事实上,MyRWST

 甚至不是一个有效的类型。它的参数之一的类型为 
Either String
,这不是 
*
 类型。您不能拥有 
Either String
 类型的值,因为 
Either String
 不是类型;它是一个类型构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.