我想使用节点和唯一键的IntMap创建图形结构 . 这个主题已经涵盖here和here . 我理解状态monad是如何工作的,基本上将状态函数 - >(val,state)包装在newtype中,这样我们就可以为它创建一个monad实例 . 我已经阅读了很多相关主题 . 我仍然无法理解如何在程序执行过程中获得唯一(或仅增量)值 . 它's easy enough to get a run of successive IDs, but once I 1123624 to get out of the monad it seems like I'回到我开始的地方,我必须跟踪当前的ID . 我觉得我被卡在了monad中 . 我考虑的另一个选项是保持整个IntMap和当前的"next" ID作为状态,但这似乎非常"imperative"和极端 . This问题非常相似,但没有得到很多答案(或者我可能只是遗漏了一些明显的东西) . 在程序执行过程中利用状态monad获取唯一ID的惯用方法是什么?谢谢 .
1 回答
让我们想象一下我们要
IO
-确认State
monad . 那会是什么样的?我们纯粹的State
monad只是一个新类型:那么,在返回最终值之前,
IO
版本可能会产生一些副作用,如下所示:这种模式很常见,它有一个名字,特别是
StateT
:该名称末尾有
T
,因为它是monadT
变形金刚 . 我们将"base monad"和StateT s m
"transformed" monad称为m
.如果
m
是Monad
,则StateT s m
仅为Monad
:但是,除此之外,所有monad变换器都实现了
MonadTrans
类,定义如下:如果
t
是StateT s
,则lift
的类型专门用于:换句话说,它让我们“提升”基础monad中的一个动作,成为变形monad中的一个动作 .
因此,对于您的特定问题,您需要
StateT (IntMap k v) IO
monad,它将IO
扩展为State
. 然后你可以在这个monad中编写你的整个程序:请注意,我仍然使用
get
和put
. 那是因为transformers
包实现了我描述的所有概念,并且它将get
和put
的签名概括为:这意味着它们会自动在
StateT
内工作 .transformers
然后只将State
定义为:这意味着您可以将
get
和put
用于State
和StateT
.要了解有关monad变换器的更多信息,我强烈推荐Monad Transformers - Step by Step .