在F#中是否有类似Array2D的List2D

时间:2016-02-06 01:20:52

标签: list f# 2d

我是否必须在所有2D操作中使用Array2D然后将它们转换为List2D?任何方便的函数调用或库来定义和操作2D列表?

1 个答案:

答案 0 :(得分:6)

简答:不,没有2d列表。

更长的回答:

我认为这样的类型在创建时会有问题,因为它的直接实现要么在其等效的cons操作上没有O(1)复杂性,要​​么破坏结构相等。

F#列表和数组并不是完全相同的。让我们回想起一些关于F#列表的事实,人们会认为它们具有2d版本。它们:

  • 是不可变的
  • 支持结构比较
  • 可以通过前置元素迭代构建

两个维度中的F#列表的等价物可以被认为是格子状结构中的矩形,例如:

    N: Node           N-N-0
    0: None           | |
                    N-N-N-0
                    | | |
                N-N-N-N-N-0
                | | | | |
                0 0 0 0 0

其中-表示左边的节点包含对右边的引用,|表示上面的节点保存对下面节点的引用。就像在一维列表中一样,每个节点将包含一个完整的2d列表,即矩形中从其自身到右下角的最后一个节点的所有元素。

由于列表应该是不可变的但允许从子列表进行迭代构造,因此通过添加节点创建新列表仅在以下三种情况下有效:

  • 新元素位于节点的最下面一行
  • 新元素位于节点的最右侧列
  • 通过从新节点向下或向右一步形成的元素(以及二维列表)是非空的,并且能够组合成一致的二维列表

这就是麻烦的来源。你怎么知道两个邻居在结构比较的世界中建立在相同的子列表上?您可以通过右下和右下路径从新节点沿对角线向下一步,看看您是否最终处于同一元素。如果结果不同(由于参数无效而失败)或引用相同(新的2d列表有效),这是好的和花花公子,但是如果它们的内容相同但是它们的身份不是什么呢?换句话说:它们是不同的对象但可能是等价的?现在,我们被迫完成整个事情并比较一切,否则我们最终可能会构建一些根本不是二维的疯狂图形。

这需要比较整个子列表,这些子列表是从新插入节点到最右下节点一步对角线的节点。那不太实际;构建像这样的n个元素的2d列表将具有O(n ^ 2) - 除非存在某种形式的优化,例如跟踪所有节点并给予等效节点唯一标识。

此时,我想我可以看到为什么这样的东西没有进入F#核心库。