list - 如何更新 Haskell 中的列表元素

我有 Python 和 Javascript 背景,我真的无法理解为什么在 Haskell 中更新列表元素并不简单。我的意思是,为什么我不能写像 myList[0] = "newValue" 这样简单的东西?

所以,我有两个问题:

  1. 为什么在 Haskell 中更新列表的元素不直接?我希望能在这里得到一些理论上的回应。
  2. 如何着手更新列表的元素?到目前为止,我的方法是重新创建整个列表,同时更新我感兴趣的元素。但这种方法似乎性能不佳。

最佳答案

这与列表无关。有意地,在 Haskell 中根本不可能更新任何值。

为什么?好吧,这就是语言的设计方式。您可能还会问为什么命令式语言允许更新值。我是说,你写

x = 3

然后你写

x = 4

什么?那么第一个是谎言还是什么?当然,我们应该明确指出我们指的是两个不同的时间变量。这只是 bug!当然,仅仅保存一些字符并启用一些也可以通过其他更安全的方式实现的低级优化是不值得的吗?
...对不对?

即使在命令式语言中,更新(链接)列表中的值实际上也没有多大意义——无论如何你需要遍历 O(n)个参数甚至到达应该更改的那个。创建一个全新的列表平均只需要更改旧列表的两倍时间,但与命令式更新不同,你永远不需要担心其他东西是否仍然需要旧版本,因为你永远不会干扰它。

而且链表通常非常慢,所以担心 2× 因子也没有多大意义。但是,GHC 通常会完全优化列表,因此它们实际上根本不会在内存中构建,如果编译器不得不担心某些事情,那将是编译器难以保证的事情之一在其他地方改变列表。

更新数组中的元素,那是另一回事。事实上,更新数组中的值在 Haskell 中也很常见,对于可以带来重要性能提升的应用程序。仍然不可能更新数组类型的值,但可以通过对单子(monad)可变数组的引用来更新值。这最终看起来与您在命令式语言中更新数组的方式非常相似,尽管它通常有点冗长,因为所有数组工具都需要从库中导入,而不是使用内置语法。

import qualified Data.Vector.Mutable as VM

main :: IO ()
main = do
  myArray <- VM.generate 37 (const "this element isn't set yet")
  print =<< VM.read myArray 0
  VM.write myArray 0 "newValue"
  print =<< VM.read myArray 0      

等效的 Python:

def main():
    myArray = ["this element isn't set yet"] * 37
    print(myArray[0])
    myArray[0] = "newValue"
    print(myArray[0])

但是,很多时候您并不是真的需要更新元素。事实上,我们立即在这里看到了一个问题:您正在索引到一个数组中。这意味着您需要确保索引确实存在。在命令式语言中,这很常见,你几乎不会去想它,但在 Haskell 中,我们真的更喜欢 total 代码,也就是说,即使我们不小心交换了两个变量(比如两个不同的循环索引),它也不应该给出运行时错误,但最好是编译器错误。

通常情况下,如果您更新单个元素,您也会更新其他元素。事实上,很多时候你会按顺序更新它们中的所有,然后从头开始简单地构建一个包含更新的新列表就没有太多优势了值马上。使用这种方法,几乎​​不会出错,至少在运行时不会出错。


这里有一个很大的警告:如果其他人仍在使用旧列表,则意味着垃圾收集器无法回收内存。这就是为什么在 Haskell 中很容易发生内存泄漏的原因——IMO 是该语言的最大问题。

https://stackoverflow.com/questions/69949373/

相关文章:

typescript - @typescript-eslint/naming-convention

javascript - 如何使用 "onclick"方法获取数据属性?

android - 找不到实现(房间)

javascript - 如何在 react-native 中结合使用 Drawer Navigat

intellij-idea - 如何将项目从 IDEA 连接到 Gitlab

flutter - 无法将类型为 'String' 的值分配给 flutter Getx 中类型为

haskell - 如何使用 `zipTree` 实现 `foldTree` ?

javascript - 从数组中创建 N 位随机单词

perl - 从包含日期的文件中排序并提取一定数量的行

python - 如何根据字典键和值过滤 Pandas 数据框行?