haskell - 真正无序的折叠包

标签 haskell types bag commutativity

我想要一个 Bag 容器,它可以向客户隐藏其“真实”订单。

它还必须是完全多态的,即不需要对其元素类型有任何约束。

我发现了至少三种包的实现:来自 ghc 包的 Bag 模块,来自 bagData.Bag > 和来自 multiset-combMath.Combinatorics.Multiset

但是,它们都有 toListfold* 操作,这些操作公开了元素的内部顺序,这些顺序可能取决于实现细节或包构造的顺序。

toList 是不可能的,至少对于 Bag a -> [a] 类型是不可能的。然而,折叠并不总是暴露顺序。

例如,fold (+) 0 不会公开。

问题是,折叠界面应该如何设计? a -> a -> a 折叠功能的安全性是否存在充要条件?由于 fmap 不公开顺序,因此使用 a -> b -> b 折叠是否会损失通用性?

我正在考虑交换幺半群 - 它们似乎足够了,但我不确定结合性和单位元素是否必要。

最佳答案

如果你的袋子可以是空的,那么身份可能是必要的 - 在这种情况下你必须返回一些东西,并且如果你希望你的折叠是同态的(这样组合折叠一些袋子的结果与折叠一个袋子相同)由袋子组合而成的袋子,这是一个非常自然的属性),它一定是一个身份元素。

同样,关联性也是一个好主意。假设我有这样的类型和操作:

data T a = Zero | One a | Two (T a) (T a)
  deriving (Eq, Ord, Show)

(+-+) :: Ord a => T a -> T a -> T a
Zero +-+ x = x
x +-+ Zero = x
a +-+ b = Two (min a b) (max a b)

显然(++-+)是可交换的并且具有恒等式,但是是非关联的。假设我然后将一个包实现为一个列表:

newtype Bag a = Bag [a]

-- pre-condition: f is commutative and z is an identity for it
foldBag :: (a -> a -> a) -> a -> Bag a -> a
foldBag f z (Bag xs) = foldr f z xs

foldNonAssoc :: (Ord a) => Bag (T a) -> T a
foldNonAssoc = foldBag (+-+) Zero

即使我要求规定的前提条件,我仍然可以使用我的 foldNonAssoc 来区分 Bag [One 1,One 2,One 3],它将折叠到两个(一个 1)(两个(一个 2)(一个 3)) 袋子 [One 3,One 2,One 1],将折叠为 两个(一 3)(二(一 1)(一 2))(请注意,并非所有结构都被保留,但在一个很长的列表中,我将获得整个列表除最后两个元素的顺序外,按顺序返回)。

先验,如果您将所有项目与操作组合起来,您将拥有一个应用程序树,类似于 a +-+ (b +-+ (c +-+ d))。交换性会让您进行一些重新排列,但无论您做什么,c 始终会与 d 组合。因此,如果您希望它与 (a +-+ c) +-+ (b +-+ d) 相同,那么您也确实需要关联性。

关于haskell - 真正无序的折叠包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12281520/

相关文章:

Haskell,一个参数的多个类型类

python csv DictReader类型

c# - 我什么时候应该使用 double 而不是十进制?

java - Java 中的参数类型

java - Java 中的 Knight's Tour(递归),使用 Graph 和 DFS

java - 在 Java 中使用 Bag

java - 在 Haskell 的类型 A 的函数中从另一个类型 B 返回一些东西

haskell - 从Haskell列表中删除重复的元素

Haskell:隐藏模块导出中的特定功能?

java - 用于计数出现次数的数据结构