haskell - 为什么 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,对细节不太确定。
谢谢,
解决方案
认为
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
两次,传递了相同的 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'
但我们不希望这样:read
即使我们传递相同的参数,我们也希望返回不同的东西,同时考虑到write
在这两者之间可能发生的任何 s。因此,read
必须是一元动作。
这与length
. 向量的长度永远不会改变,即使向量是可变的;创建时固定的长度。因此,length
是一个纯函数;在创建向量和查询其长度之间执行了什么单子操作并不重要;它总是一样的。
推荐阅读
- react-native - React Native:双击退出应用程序
- html - 很难解释,模仿这个链接栏悬停效果
- adal.js - ADAL、Angular 6 和保护 MVC API
- angular - Angular Material mat-tree 获取复选框值
- c# - 在 Windows 服务启动/自定义/UUID/data0/ 中,我的事件(如安装)的 data0 是什么?
- amazon-web-services - AWS CLI:无法连接到终端节点 URL:“https://sts.amazonaws.com/”
- javascript - 如何创建多个相同的同名容器,这些容器可以包含(并保留)不同的项目/数量
- hyperledger-fabric - Hyperledger Fabric - NodeJS SDK 查询链码
- asp.net-mvc - d3.json 不从 ASP.NET MVC 的 App_Data 文件夹加载文件
- python - python opencv先运行后乱序,这正常吗?