我目前正在研究Haskell中的一些事务性内存基准测试,并希望能够在事务中使用随机数 . 我目前正在使用here中的Random monad / monad变换器 . 在下面的示例中,我有一个包含整数的TVar数组和一个随机选择数组中10个tvar的事务,例如:
tvars :: STM (TArray Int Int)
tvars = newArray (0, numTVars) 0
write :: Int -> RandT StdGen STM [Int]
write 0 = return []
write i = do
tvars <- lift tvars
rn <- getRandomR (0, numTVars)
temp <- lift $ readArray tvars rn
lift $ writeArray tvars rn (temp + 1)
rands <- write (i-1)
lift $ return $ rn : rands
我想我的问题是"Is this the best way to go about doing this?"看起来更自然/更有效的方式,即将随机monad提升到STM monad中 . 每个事务执行很多STM操作,并且很少有随机操作 . 我会假设每个_515327都会增加一些开销 . 仅仅随机计算并单独留下STM计算会不会更有效率?这样做是否安全?似乎定义一个STM monad转换器会打破我们用STM monad获得的漂亮的静态分离属性(即我们可以将IO提升到STM monad,但是如果事务中止,我们必须担心撤消IO操作问题数量) . 我对monad变压器的了解非常有限 . 关于使用变压器的性能和相对开销的简要说明将非常受欢迎 .
1 回答
STM是一个基础monad,想想
atomically
,当前STM a -> IO a
应该是什么样的,如果我们有STMT
.我对你的特定问题的解决方案很少 . 更简单的可能是重新安排代码:
然而
RandT
基本上StateT
与lift
:所以形式代码:
将会
在desugaring做符号之后
首先内联
>>=
StateT
和runStateT
取消:经过几次内联/缩小步骤:
可能GHC足够聪明,可以进一步降低这一点,所以状态只是在没有创建中间对的情况下通过(但我不确定,应该使用monad法则来证明这一点):
这是你得到的