2013-06-29 15 views
1

所以我想創建一個工作方式寫作鏈突變/修改功能可變的載體

import Data.Vector as V 
import Data.Vector.Mutable as MV 
import Control.Monad.ST 

type DoubleVec = V.Vector Double 

incrAndSwap :: DoubleVec -> Int -> Int -> Int -> DoubleVec 
incrAndSwap vec i a b = runST $ do 
    mvec <- V.thaw vec 
    oldval <- MV.read mvec i       -- 1 
    MV.write mvec i (val + 1)       -- 2 
    MV.swap mvec a b 
    V.freeze mvec 

但能夠在兩個標線「濃縮」到一個功能,並能夠同樣的方法要說:

incrAndSwap :: DoubleVec -> Int -> Int -> Int -> DoubleVec 
incrAndSwap vec i a b = runST $ do 
    mvec <- V.thaw vec 
    incrAt mvec i 
    MV.swap mvec a b 
    V.freeze mvec 

基本上寫的是incrAt i函數。

我試過複製MV.write的類型簽名,但我一直沒有能夠得到任何與類型簽名一起工作;沒有編譯。

這是我最近嘗試

import Control.Monad.Primitive 

type MDoubleVec s = MV.STVector s Double 

incrAt :: (PrimMonad m) => MDoubleVec (PrimState m) -> Int -> m() 
incrAt mvec i = MV.write mvec i (val + 1) 
    where 
    val = MV.read mvec i   -- val is stuck in monad m0 

但我不知道怎麼去val出來的單子m0 - 這是在,顯然,根據編譯器。這是有道理的。

有誰知道我該怎麼做?

回答

3

您需要在m monad中執行MV.read,並將其結果綁定到val。基本上,它是接受原代碼的兩行和逐字移動它們的問題:

incrAt :: (PrimMonad m) => MDoubleVec (PrimState m) -> Int -> m() 
incrAt path i = do 
    val <- MV.read path i 
    MV.write path i (val + 1) 

BTW,只爲您的信息,該類型錯誤中提到m0的原因,而不是m(這可能會造成混亂)是在你的代碼中,沒有任何關聯單元格的地方將val定義到了monad,你在那裏做了MV.read。但真正的問題是,MV.read是monadic,所以你需要綁定它的結果,以便能夠在一元MV.write中使用它。