haskell - 如何修改或读取作为函数参数传递的可变向量?

  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 向量。所以……

最佳答案

您可能需要一些示例。这是一个基本的评论,但我相信如果您稍微谷歌一下,您会在网上找到其他评论。

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 绝不能返回任何指向已分配内存的“指针”。当 runST 返回时,可以释放可变事物的每个分配。因此,典型的 ST s 计算仅在最后执行 runST,此时它准备好丢弃所有可变数据并保留其中的不可变部分。在上面的示例中,不可变部分是第 4 个元素(像往常一样从 0 开始计数),它是一个不可变的 Int

如果您不熟悉 ST s,我建议您暂时忘记向量,并使用 STRef s Int 进行一些练习(引用 Int) 和 ST。任何 ST 教程就足够了。

https://stackoverflow.com/questions/37751142/

相关文章:

php - 如何在 php 中使用 in_array 并将数组作为针,但在至少有一个值匹配时返回 t

oracle - 为什么我不能使用 SQLcl 通过 jdbc 连接

javascript - 在 React 中停止路由更改的音频?

macos - 通过 PIP 安装 NPM,但得到 "npm: command not found"

python - Sqlalchemy,递归获取具有关系的子项和祖先

php - Eloquent 模型添加没有 "created_at"和 "updated_at"字段

git - 从 merge 请求创建补丁

assembly - GDB - 它如何知道函数调用堆栈?

angularjs - 具有自动完成功能的 Angular 下拉菜单

Neo4j - 根据关系属性查找两个节点之间的最短路径