2016-06-10 38 views
1
test :: VM.MVector s Int -> Int 
    test x = runST $ do 
    a <- return x 
    VM.read a 0 -- Type error 

我想弄清楚如何不把一個ST monad中的所有東西都放到一個函數中。如果我試圖修改x或從中返回值,編譯器會抱怨可變向量的狀態部分不匹配。如何修改或讀取作爲函數參數傳遞的可變向量?

在Haskell中可能對傳遞的可變向量進行操作嗎?還是必須在對它們做任何事情之前將它們凍結到不可變對象中?

編輯:

這是實際的錯誤。

Couldn't match type `s1' with `s' 
    `s1' is a rigid type variable bound by 
     a type expected by the context: ST s1 Int at rjb.hs:17:12 
    `s' is a rigid type variable bound by 
     the type signature for test :: VM.MVector s Int -> Int 
     at rjb.hs:16:11 
Expected type: VM.MVector 
       (Control.Monad.Primitive.PrimState (ST s1)) Int 
    Actual type: VM.MVector s Int 
Relevant bindings include 
    a :: VM.MVector s Int (bound at rjb.hs:18:5) 
    x :: VM.MVector s Int (bound at rjb.hs:17:8) 
    test :: VM.MVector s Int -> Int (bound at rjb.hs:17:3) 
In the first argument of `VM.read', namely `a' 
In a stmt of a 'do' block: VM.read a 0 

編輯:以下通過類型檢查。

test :: VM.MVector (Control.Monad.Primitive.PrimState IO) Int -> IO (Int) 
    test x = VM.read x 0 

我在猜測我也可以改變x矢量。所以...

+0

請問您可以添加實際的錯誤嗎? – Carsten

+0

'a < - return x'是多餘的。這只是給你'x'。 – melpomene

+0

@Carsten增加了錯誤。 –

回答

5

你可能需要一些例子。這裏有一個基本的評論,但我相信你會在網上找到其他人,如果你有一點谷歌。

import Control.Monad.ST 
import qualified Data.Vector.Mutable as VM 

-- This returns a reference to a vector, wrapped in the ST s monad. 
test :: ST s (VM.MVector s Int) 
test = do 
    v <- VM.new 10  -- create vector 
    VM.write v 3 2000 -- modify it 
    VM.write v 4 3000 
    x <- VM.read v 3  -- access it 
    VM.write v 4 (x+1) 
    return v    -- return it 

-- This instead returns a (wrapped) Int 
test2 :: ST s Int 
test2 = do 
    v <- test   -- call test, which performs the allocation 
    VM.read v 4   -- return v[4] 

-- This returns a plain pure Int value  
test3 :: Int 
test3 = runST test2 

注意到,當x類型是 多種類型ST s T其中T不涉及類型變量srunST x才能使用。 這就是ST monad如何實現參照透明度。

用更簡單的術語來說,這意味着任何分配內存的「指針」絕對不能由runST返回。當runST返回時,可以釋放每個可變事物的分配。因此,一個典型的ST s計算只在最後完成runST,當它準備扔掉所有可變數據並保留它的不可變部分時。在上面的例子中,不可變的部分是第4個元素(像往常一樣從0開始計數),這是不可變的Int

如果你不熟悉ST s,我建議你忘記的時刻向量,並做一些練習與STRef s Int(引用Int)和ST。任何ST教程就足夠了。

+0

對,這就是我一直在尋找的東西。這就是ST monad類型簽名的樣子。可變向量和ST monad具有相同的「s」類型。其實,ST'S(VM)裏面的東西是什麼?MVector's Int)'應該除了防止我無意中突變載體之外呢? –

+5

@MarkoGrdinic's'是一個虛擬類型,它可以像「STRef s Int」或「MVector s Int」那樣「污染」所有「攜帶指針」的東西。它的目的是防止你從'runST'返回這些「指針」,沒有別的 - 只是向編譯器證明你是由規則玩的。 – chi

+0

@chi IIRC這也是爲了防止你在單獨的內存塊上不安全地交錯ST操作。所以你不能嘗試在'bar'內引用塊'foo'中創建的指針而不先運行全部'foo'。 – semicolon

相關問題