使用带有STM和确定性IO的Par monad

Dav*_*ave 1 parallel-processing monads concurrency haskell stm

我正在编写一份报告,其中我使用STM包实现了并发多核分支和绑定算法,我遇到了一个问题.

使用STM的实现显然在IO monad中,因为它既使用STM的'atomically'和Concurrent的'forkIO',但它是确定性的.尽管使用了共享内存变量,但对于同一输入,函数的最终结果将始终相同.

我的问题是,除了'unsafePerformIO'之外,在退出IO时我有哪些选择?我是否应该尝试将其从IO monad中删除,因为使用多个内核可能会影响其他并发代码,这些代码对确定性没有相同的保证.

我听说过Par monad包(尽管没有使用它),但STM存在于IO monad中,为了获得线程安全的全局变量,我唯一替代STM的是MVars(我知道),也存在于IO monad中.

Tho*_*son 6

请不要将unsafePerformIO与STM一起使用.STM在引擎盖下有副作用,使用unsafePerformIO会隐藏这些副作用,使你的代码看起来不纯净,因此重构很难或很危险.更加努力地看看并行包是否会对您有所帮助.

不安全的STM操作不安全的一个例子是当你最终使用嵌套在另一个内部的"纯"STM操作时(可能是由更高级别的库).例如,<loop>由于嵌套的STM操作,下面的代码循环(终止).我记得较旧的GHC版本崩溃但现在似乎无法使用GHC 7.0.1重现这种行为.

import Control.Concurrent
import Control.Concurrent.STM
import System.IO.Unsafe
import GHC.Conc.Sync

main = newTVarIO 5 >>= runComputation >>= print

runComputation :: TVar Int -> IO Int
runComputation tv = atomically $ do
        let y = getFiveUnsafe tv + 1
        writeTVar tv y
        return y

getFiveUnsafe tv = unsafePerformIO . atomically $ do
        x <- readTVar tv
        writeTVar tv (x + 5)
        return x
Run Code Online (Sandbox Code Playgroud)

(我欢迎其他人编辑和添加更有说服力的例子 - 我相信存在更好的例子)