在这里查看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
Run Code Online (Sandbox Code Playgroud)
由于读取操作不会修改向量,所以我的主要问题是为什么不这样做:
read :: PrimMonad m => MVector (PrimState m) a -> Int -> a
Run Code Online (Sandbox Code Playgroud)
可变向量的长度在向量上也做不可变的事情,其类型 MVector s a -> Int看起来很正常。不是PrimMonad m => MVector (PrimState m) a -> m Int。那么,为什么在读取和长度之间做出设计选择上的差异,因为它们都是向量上的不变操作?
现在我考虑一下,以某种方式读取返回的单元格是对向量内部单元格的引用,而不是其数据的副本吗?如果是这样,我怎么能以可变的向量很好且廉价地获得对第n个元素的不变访问?我正在学习haskell,但不太了解细节。
谢谢,
假设
read :: MVector s a -> Int -> a
Run Code Online (Sandbox Code Playgroud)
这意味着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'
Run Code Online (Sandbox Code Playgroud)
有什么地方出了问题:我写了read cell 1两次,传递相同 cell和1参数,所以两个调用应该返回相同的值。这就是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'
Run Code Online (Sandbox Code Playgroud)
但是我们不希望这样:read即使在传递相同的参数时,我们也想返回不同的东西,要考虑到write它们之间可能发生的任何变化。因此,read必须采取单行动。
这与有所不同length。即使向量是可变的,向量的长度也不会改变。在创建时固定的长度。因此,length 是一个纯函数;在创建矢量和查询其长度之间执行了什么单调操作都无关紧要;它将永远是相同的。
考虑
foo = do
...
x1 <- read vector 3
write vector 3 something
x2 <- read vector 3
return (x1 == x2)
Run Code Online (Sandbox Code Playgroud)
如果read变成非单子,我们可以这样写
foo = do
...
let x1 = read vector 3
write vector 3 something
let x2 = read vector 3
return (x1 == x2)
Run Code Online (Sandbox Code Playgroud)
通过引用透明度,这相当于
foo = do
...
let x1 = read vector 3
write vector 3 something
let x2 = x1
return (x1 == x2)
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个问题:最后一个片段总是True在最后返回,而第一个片段则不会。所以这两个片段并不真正等同。
读取必须被视为一种效果,不是因为它可以从外部观察到(事实并非如此),而是因为它根据受写入影响的向量状态产生不同的结果。
| 归档时间: |
|
| 查看次数: |
64 次 |
| 最近记录: |