如何修改或读取作为函数参数传递的可变向量?
How to modify or read a mutable vector passed as an argument in a function?
test :: VM.MVector s Int -> Int
test x = runST $ do
a <- return x
VM.read a 0 -- Type error
我想弄清楚如何不将 ST monad 中的所有内容放入单个函数中。如果我尝试修改 x
或 return 中的一个值,编译器会抱怨可变向量的状态部分不匹配。
在 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
向量。所以...
您可能需要一些示例。这是一个基本的评论,但我相信如果你 google 一点,你会在网上找到其他人。
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
注意runST x
只有在x
的类型是
polytype ST s T
其中 T
不涉及类型变量 s
。
这就是 ST monad 实现引用透明性的方式。
用更简单的术语来说,这意味着 runST
绝不能返回分配给内存的任何 "pointer"。当 runST
returns 时,可以释放可变事物的每个分配。因此,典型的 ST s
计算仅在最后执行 runST
,当它准备好丢弃所有可变数据并保留其中的不可变部分时。在上面的示例中,不可变部分是第 4 个元素(像往常一样从 0 开始计数),这是一个不可变的 Int
.
如果您不熟悉 ST s
,我建议您暂时忘记向量,并使用 STRef s Int
(参考 Int
)和 ST
。任何 ST
教程就足够了。
test :: VM.MVector s Int -> Int
test x = runST $ do
a <- return x
VM.read a 0 -- Type error
我想弄清楚如何不将 ST monad 中的所有内容放入单个函数中。如果我尝试修改 x
或 return 中的一个值,编译器会抱怨可变向量的状态部分不匹配。
在 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
向量。所以...
您可能需要一些示例。这是一个基本的评论,但我相信如果你 google 一点,你会在网上找到其他人。
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
注意runST x
只有在x
的类型是
polytype ST s T
其中 T
不涉及类型变量 s
。
这就是 ST monad 实现引用透明性的方式。
用更简单的术语来说,这意味着 runST
绝不能返回分配给内存的任何 "pointer"。当 runST
returns 时,可以释放可变事物的每个分配。因此,典型的 ST s
计算仅在最后执行 runST
,当它准备好丢弃所有可变数据并保留其中的不可变部分时。在上面的示例中,不可变部分是第 4 个元素(像往常一样从 0 开始计数),这是一个不可变的 Int
.
如果您不熟悉 ST s
,我建议您暂时忘记向量,并使用 STRef s Int
(参考 Int
)和 ST
。任何 ST
教程就足够了。