【问题标题】:Why doesn't Haskell provide folds for one-dimensional Arrays?为什么 Haskell 不为一维数组提供折叠?
【发布时间】:2012-09-09 00:48:49
【问题描述】:

Data.Array 不提供 Array 类型的折叠。

在 Real World Haskell(第 12 章)中,据说原因是 Arrays 可以根据程序员的需要以不同的方式折叠:

首先,有几种折叠是有意义的。我们可能仍然想要折叠单个元素,但我们现在也可以折叠行或列。最重要的是,对于一次元素的折叠,不再只有两个序列用于遍历。

Lists 不正是这样吗?表示例如是很常见的。具有多维 List 的矩阵,但仍然为一维 Lists 定义了折叠。

我缺少什么微妙之处?是不是多维的ArrayArrays 的Array 有很大的不同?

编辑:嗯,即使是多维数组也确实定义了折叠,以Data.Foldable的实例的形式。[0]那么,这与 Real World Haskell 的引用有什么关系呢?

[0]http://hackage.haskell.org/packages/archive/base/4.6.0.0/doc/html/Data-Foldable.html

【问题讨论】:

  • 多维数组和嵌套列表的区别在于所有数组的类型基本相同:Array Int eArray (Int,Int) eArray (Int,Int,Int) e...。所以你不能创建一个只为一维数组定义的函数,而foldr 接受一个列表列表并逐个列表处理它,而不是连接所有列表并逐个元素处理它。

标签: higher-order-functions haskell


【解决方案1】:

既然您提到了“多维”ArrayArrays 中的Array 之间的区别,这将很好地说明这一点,并与列表进行比较。

折叠(在Foldable 类的意义上)本质上是线性操作,就像列表本质上是线性结构一样;右折叠通过将其构造函数与foldr 的参数一一匹配来完全表征列表。虽然您也可以定义 foldl 之类的函数,但可以明确选择标准的规范折叠。

Array 没有这样的透明结构,可以在折叠中一对一匹配。它是一种抽象类型,可以访问由索引值提供的各个元素,索引值可以是具有Ix 实例的任何类型。因此,实现折叠不仅没有单一的明显选择,也没有内在的线性结构。碰巧Ix 允许您枚举一系列索引,但这更像是一个实现细节。

多维Arrays呢?它们实际上并不存在。 Ix 为同样是实例的类型的元组定义实例,如果您想将此类元组视为“多维”Array 的索引类型,请继续!但它们仍然只是元组。显然,Ix 对这些元组设置了一些线性顺序,但它是什么?你能在文档中找到任何告诉你的东西吗?

所以,我认为我们可以肯定地说,使用 Ix 定义的顺序折叠多维 Array 是不明智的,除非您并不真正关心获取元素的顺序。

另一方面,对于Arrays 中的Array,只有一种合理的方法可以组合它们,就像嵌套列表一样:根据自己的元素顺序分别折叠每个内部Array,然后折叠每个根据外部Array的元素顺序的结果。


现在,您可能有理由反对,因为一维和多维 Arrays 之间没有类型区别,并且可以假设前者具有基于 Ix 实例的合理折叠排序,为什么不直接使用默认情况下排序?毕竟,已经有一个函数可以在列表中返回 Array 的元素。

事实证明,库本身会同意你的观点,因为这正是 Foldable 实例所做的。

【讨论】:

    【解决方案2】:

    有一种自然的折叠列表方式,即foldr。注意列表构造函数的类型:

    (:) :: a -> [a] -> [a]
    []  :: [a]
    

    将出现的[a] 替换为b,我们得到这些类型:

    f :: a -> b -> b
    z :: b
    

    当然,现在foldr的类型就是基于这个原则:

    foldr :: (a -> b -> b) -> b -> [a] -> b
    

    因此,鉴于列表的构造/观察语义,foldr 是最自然的一种。您可以将类型解读为“告诉我如何处理 (:) 以及如何处理 [],我会为您删除一个列表。”

    Array 没有这个属性;您从关联列表 (Ix i => [(i,a)]) 构建一个数组,并且该类型并没有真正公开任何递归结构:一个数组不会像列表或树那样通过递归构造函数从其他数组构建。

    【讨论】:

    • +1 表示“告诉我如何处理(:) 以及如何处理[],我会为你删除一个列表。” - 我真的很喜欢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多