Mar*_*nic 1 monads haskell vector mutable
test :: VM.MVector s Int -> Int
test x = runST $ do
a <- return x
VM.read a 0 -- Type error
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚如何不将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
Run Code Online (Sandbox Code Playgroud)
编辑:以下传递类型检查.
test :: VM.MVector (Control.Monad.Primitive.PrimState IO) Int -> IO (Int)
test x = VM.read x 0
Run Code Online (Sandbox Code Playgroud)
我猜我也能改变x矢量.所以...
你可能需要一些例子.这是一个基本评论,但我相信如果你谷歌一点,你会在网上找到其他人.
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
Run Code Online (Sandbox Code Playgroud)
需要注意的是runST x,只能使用时的类型x是多种类型ST s T,其中T不涉及的类型变量s.这就是ST monad实现参考透明度的方式.
换句话说,这意味着永远不能返回分配内存的任何"指针" runST.当runST返回时,可变的东西每个分配可以被释放.因此,典型的ST s计算runST只在最后执行,当它准备扔掉所有可变数据并保留它的不可变部分时.在上面的例子中,不可变部分是第4个元素(像往常一样从0开始计算),这是一个不可变的Int.
如果你不熟悉ST s,我建议你暂时忘记矢量,并做一些练习STRef s Int(参考Int)和ST.任何ST教程都足够了.