考虑以下:
do
x1 <- new 2
set x1 3
x2 <- get x1
y1 <- new 10
set y1 20
y2 <- get y1
return (x2 + y2)
我想要这导致 23
. 有没有办法在纯Haskell中实现这样的东西,如果是这样的话怎么样?我理解 STRef
做了类似的事情,但我只是想在普通的Haskell中做到这一点(现在不担心效率) . 我假设我必须创建一个数据类型并使其成为 Monad
的实例,但我不确定细节,所以一个有用的例子会有所帮助 .
4 回答
在
Control.Monad.State
中已经有了一个实现,但是为了一般性起见它很麻烦:一个复杂性来自MonadState类,另一个来自于普通State
是用更通用的StateT
来实现的 .以下是使用该实现的任务示例 . 没有使用可变性 . 请注意,您的示例按原样粘贴,只需添加
x
前缀:可以实现模块中的所有功能和
>>=
/return
,而无需使用Control.Monad
中保留签名的库存实现 .这里是:
将其保存到
MyState.hs
并将import Control.Monad.State
替换为import MyState
.使用
State
或StateT
可以模拟它(State
仅允许1个值) . 最简单的方法是使用Map
:StateT for a tuple怎么样?
如果你真的想要可变的单元格,我建议使用ST,STM或IO而不是StateT . 使用StateT在异构映射中实现从增加自然到对象的实现似乎是可能的,但可能有点尴尬 .
这允许多个值,但是_218800_建议
Dynamic
.然后使用它
Ref
s基本上是Int
s,附有一些类型信息,val
将查找相应的Dynamic
并尝试强制它进入正确的类型 .如果这是真正的代码,您应该隐藏
Ref
和MutState
的实现 . 为方便起见,如果你想要一个安全的实现,我已经fromJust
返回了val
bur我想你可以将State
和Maybe
monads分层来处理未绑定的变量 .如果您担心类型限制,如上所示,它们可以简单地推导出来 .