提问人:Piskator 提问时间:10/9/2023 最后编辑:Piskator 更新时间:10/9/2023 访问量:82
了解 Haskell 中的 RWST
Understanding the RWST in Haskell
问:
我研究了这个,试图理解几个变压器单子是如何相互作用的,特别是更好地理解单子并堆叠在一起。lift
对于这里找到的 RWST 单子(我认为这是最好的文档),它是一个堆叠的单子,其中 Reader、Writer、State 都是一个单子层(并且按照堆叠的顺序)。或者应该如何理解它?
当我查看定义时,我将其理解为将 reader-environment 视为状态环境,并将任何 monad 包装在 的返回值周围。这也意味着在这个单子中只存在两层单子。即,外部单子和包含多个单子的元组。runRWST :: r -> s -> m (a, s, w)
m
RWS
m
这反过来也意味着您只能使用一次。将值从读取器或状态单子提升到外部单子中。lift
从这个意义上说,它只是两个函数应用两个内部单子中的任何一个。对于最后一点,我仍然不确定我是否理解为什么即使阅读了这篇 stackoverflow 帖子,您也需要一个读者和一个状态单子。我猜读者只对只读有意义,但如果有人不想这样做,是否可以在两个分离状态单子周围使用变压器单子?get
ask
举个例子:
这些评论让我有理由思考并使以下内容更加明确......在以下类型定义中,什么是内部单子和外部单子?它本身是一个包裹着的单子(因此是一个外单子)(内单子)吗?RWST
Either String
type MyRWST a = RWST
(String -> Either String MyType)
[Int]
(MyEnv, [String], [String])
(Either String)
a
答:
monad transformer 的内部 monad 始终是一个类型参数。您提供的类型不是转换器。
type MyRWST a = RWST
(String -> Either String MyType)
[Int]
(MyEnv, [String], [String])
(Either String)
a
这是一个 .将其与 MaybeT
等变压器进行比较。Monad
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
MaybeT
接受两个类型参数,第一个本身接受一个参数,所以它的种类是 。使用更明确的括号,即 .现在我们可以看到为什么它被称为变压器了。它接受一个单子(种类)并将其转换为一个新的单子(也是种类)。(* -> *) -> * -> *
(* -> *) -> (* -> *)
* -> *
* -> *
RWST
定义为
newtype RWST r w s m a = RWST { unRWST :: r -> s -> w -> m (a, s, w) }
现在这需要很多类型参数,但是如果我们修复 、 和 ,我们就会得到一个转换器。也就是说,它本身不是一个单子变压器,但对于任何 , , 和 ,都是一个变压器。完整的种类是r
w
s
RWST
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
评论
MyRWST
data
type
RWST
评论
ReaderT
WriterT
StateT
lift
IO
a
runRWST :: r -> s -> m (a, s, w)
m