首页 > 解决方案 > 为什么 Data.Vector.Mutable read() 会在 monad 中返回,因为它是一个不可变的操作?

问题描述

看这里http://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector-Mutable.html 可以看出读取的类型是:

read :: PrimMonad m => MVector (PrimState m) a -> Int -> m a

由于读取操作不会修改向量,我的主要问题是为什么不是:

read :: PrimMonad m => MVector (PrimState m) a -> Int -> a

可变向量的长度也在向量上做不可变的事情,它的类型 MVector s a -> Int看起来很正常。它不是PrimMonad m => MVector (PrimState m) a -> m Int。那么为什么在 read 和 length 之间做出这种设计选择的差异,因为它们都是向量上的不可变操作?

现在我想一想,read返回的单元格是否是对向量内单元格的引用而不是其数据的副本?如果是这样,我怎样才能又好又便宜地获得对可变向量中第 n 个元素的不可变访问?我正在学习haskell,对细节不太确定。

谢谢,

标签: haskellvector

解决方案


认为

read :: MVector s a -> Int -> a

这意味着read是纯粹的。考虑

main :: IO ()
main = do
  cell <- replicate 1 'a' -- cell = ['a']
  print $ read cell 1 -- we want to print 'a'
  write cell 1 'z' -- cell = ['z']
  print $ read cell 1 -- we want to print 'z'

出了点问题:我写了read cell 1两次,传递了相同的 cell1参数,所以两个调用应该返回相同的值。这就是read纯洁的意思。以上应该等于

main :: IO ()
main = do
  cell <- replicate 1 'a' -- cell = ['a']
  let contents = read cell 1 -- contents = 'a'
  print contents -- prints 'a'
  write cell 1 'z' -- cell = ['z']; definitely should not affect contents
  print contents -- prints 'a'

但我们不希望这样:read即使我们传递相同的参数,我们也希望返回不同的东西,同时考虑到write在这两者之间可能发生的任何 s。因此,read必须是一元动作。

这与length. 向量的长度永远不会改变,即使向量是可变的;创建时固定的长度。因此,length 一个纯函数;在创建向量和查询其长度之间执行了什么单子操作并不重要;它总是一样的。


推荐阅读