2011-10-14 15 views
1

我正在編寫一個報告,其中我使用STM包實現了一個併發多核分支和綁定算法,並且出現了一個我已經提出的問題反對。使用Par monad與STM和確定性IO

使用STM的實現顯然是在IO monad中,因爲它使用STM的'原子'和Concurrent的'forkIO',但它是確定性的。儘管使用了共享內存變量,但函數的最終結果對於相同的輸入始終是相同的。

我的問題是,除了'unsafePerformIO'之外,我還有什麼選擇擺脫IO呢?我甚至應該嘗試將它從IO monad中解放出來,因爲使用多個內核可能會影響其他併發代碼,這些代碼不具有確定性的相同保證。我已經聽說過Par monad包(雖然沒有用過),但是STM存在於IO monad中,爲了獲得線程安全的全局變量,我唯一的選擇是STM是MVars(我知道),這也存在於IO monad中。

+0

在'Par'單子線程安全的全局變量['IVar's](http://hackage.haskell.org/packages/archive/monad-par /0.1.0.1/doc/html/Control-Monad-Par.html#t:IVar)。 –

回答

5

請不要在STM中使用unsafePerformIO。 STM在引擎蓋下有副作用,使用unsafePerformIO隱藏了這些副作用,使得你的代碼看似不純,因而對重構來說很難或者很危險。儘量查看平行軟件包是否會對您有所幫助。

不安全的STM操作不安全的一個例子是最終使用嵌套在另一個(可能是更高級別的庫)內的「純」STM操作。例如,由於嵌套的STM操作,下面的代碼循環(終止於<loop>)。我記得以前的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 

(我歡迎其他人編輯和添加更具說服力的例子 - 我相信更好的存在)

+0

感謝您的意見。這不是我要求從IO單子中刪除我的功能的要求,這只是我的寵物好奇心,如果我(呃)有時間,我會如何去做。我主要是問,因爲我知道這是可能的,因爲函數是純粹的。唯一的問題是是否存在提供所需功能的庫。編輯:假設函數是純粹的。 – Dave

0

STM和它相關的功能不能從unsafePerformIOforkIO使用就可以了,新的線程可以調用atomically安全。你可以做這樣的事情:

purifiedAlgorithm = unsafePerformIO $ do 
    rr <- newEmptyMVar 
    forkIO $ concurrentAlgorithm >> putMVar rr 
    takeMVar rr