在 Elm 中,字典和记录有什么区别?

10
在实现一个简单应用程序时,我遇到了尝试更新嵌套记录的问题。我在网上找到了一种解决方案,但看起来代码很臃肿。
当我寻找替代方案时,我发现了字典。这似乎是解决这个问题的一种方法--如果我在记录内部使用字典,就可以避免所有那些臃肿的代码并获得嵌套的更新。
看到字典和记录并排放在一起让我想到,为什么我要使用记录而不是字典,或者反之呢?它们对我来说非常相似,所以我不确定我是否看到了其中一个的优势。当然,我可以看到语法上的区别,但只有这些吗?
我在某个地方学到过Dict的访问时间复杂度是O(log(n))--它在键上进行二分查找吗?--但我找不到记录的访问时间复杂度,但我想知道它是否是O(1),这是其中一个优点。
无论如何,它们在其他语言中似乎都映射到1个单一的数据结构(例如Python的字典、JS对象、Java哈希表),为什么我们在elm中需要两个呢?
1个回答

15

Dict 和记录在 JavaScript 中看起来非常相似,但在静态类型语言中实际上非常不同。我认为它们唯一共有的属性是它们都是键值容器。

最大的区别是,Dict 是同构的,也就是说,值必须是相同的类型,并且“动态”地键入和调整大小,这意味着键不会在编译时进行静态检查,而且可以在运行时添加键值对。另一方面,记录在记录类型中包含键名和值类型,这意味着它们可以容纳不同类型的值,但是无法在运行时添加或删除键而不改变类型本身。

易于插入和更新 Dict 的好处是当你尝试从中取回值时需要付出代价。 Dict.get 返回一个 Maybe , 所以你需要处理它,因为类型不能保证其包含任何内容。如果您拼错了键的名称,还不会得到编译器错误。

总的来说,Dict 放弃了静态类型带来的大部分好处。如果你知道键名,最好使用记录。如果不知道,就用 Dict

你提到的性能看起来也差不多,但我认为这是次要的问题。因为在编译时已经知道了许多信息,可以将其编译成固定大小的数组,所以记录访问应该与按索引访问数组元素相当。


是的,那很有道理。我其实刚遇到了值必须同质的“问题”。在我看来,字典更像是列表的替代品,当你有某种键来索引元素时,而不是记录的替代品。 - Nicola Pedretti
1
你可以始终使用自定义类型来包含不同类型的值,但这会使得将它们取出变得更加麻烦。 - glennsl
是的,编译器建议实际上这样做。 - Nicola Pedretti
@glennsl 如果记录允许在运行时添加键,但不允许删除键(因为这将违反静态类型保证),那么你就可以同时获得最佳效果了,不是吗? - Magne
这意味着您不能再将其优化为具有索引访问的数组,但除此之外肯定可以。我想Elm甚至在某个时候也有这个功能,但它被删除了,因为它是一个很少使用且相当复杂的功能。 - glennsl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接