在Haskell中,多指数集合最惯用的方法是什么?

时间:2011-07-13 01:12:49

标签: haskell

在C ++和其他语言中,附加库实现了一个多索引容器,例如: Boost.Multiindex。也就是说,一个集合存储一种类型的值,但在这些值上保持多个不同的索引。这些索引提供不同的访问方法和排序行为,例如, map,multimap,set,multiset,array等。多索引容器的运行时复杂性通常是各个索引复杂性的总和。

是否存在Haskell的等价物或者人们自己编写?具体来说,使用set-type索引(T是Ord的实例)以及map类型的索引(假设键值)实现类型T集合的最惯用方法是什么?可以为每个T提供类型K,可以是明确地还是通过函数T -> K)?

5 个答案:

答案 0 :(得分:7)

我今天上午刚刚将IxSet上传到hackage,

http://hackage.haskell.org/package/ixset

ixset提供具有多个索引的集合。

ixset已经存在了很长一段时间,因为我很快乐。此版本删除了特定于happstack的任何依赖项,并且是IxSet的新官方版本。

另一种选择是kdtree:

darcs获得http://darcs.monoid.at/kdtree

kdtree旨在通过提供更高的类型安全性和更好的时间和空间使用来改进IxSet。当前版本似乎在所有这三个方面都做得很好 - 但它尚未准备好迎接黄金时段。其他贡献者将受到高度欢迎。

答案 1 :(得分:6)

在每个元素都有一个始终可用的唯一键的简单情况下,您可以使用Map并提取键来查找元素。在稍微不那么简单的情况下,每个值只有 一个密钥可用,一个简单的解决方案就像Map K (Set T)。直接查找元素将涉及首先提取密钥,索引Map以找到共享该密钥的元素集,然后查找所需的元素。

在大多数情况下,如果可以通过上述方式(简单的转换和嵌套)直接进行某些操作,那么以这种方式进行操作可能是有意义的。然而,由于显而易见的原因,这些都不能很好地概括为例如可能不可用的多个独立密钥或密钥。

除此之外,我不知道任何广泛使用的标准实现。确实存在一些例子,例如IxSet from happstack似乎大致符合法案。我怀疑这种大小适中的解决方案可能会带来很差的收益/复杂度,因此人们倾向于自己推出以满足特定需求。

直观地说,这似乎是一个问题,可能更好地工作,而不是作为单个实现,而是可以比Data.Map允许更灵活地组成的基元集合,以创建特殊的专用结构。但这对短期需求并没有多大帮助。

答案 2 :(得分:4)

对于此特定问题,您可以使用Bimap。但是,一般情况下,我不知道多图或多索引容器的任何常见类。

答案 3 :(得分:2)

我认为最简单的方法就是使用Data.Map。虽然它被设计为使用单个索引,但是当您多次插入相同的元素时,大多数编译器(当然GHC)会将值放在同一个位置。多图的单独实现效率不高,因为你想根据它们的索引找到元素,所以你不能天真地将每个元素与多个索引相关联 - 比如[([key], value)] - 因为这样效率非常低。 / p>

但是,我没有看过Multimaps的Boost实现,最后确定是否存在这样做的优化方法。

答案 4 :(得分:2)

我是否直接遇到了问题? T和K都有订单。有一个功能键:: T - > K但它不是保留订单。期望通过T顺序和K顺序管理Ts的集合,索引(用于快速访问)。更一般地,人们可能想要由一堆订单key1 :: T - >索引的T元素的集合。 K1,... keyn :: T - > Kn,碰巧这里key1 = id。那是图片吗?

我认为我同意gereeter的建议,即解决方案的基础只是保持同步一堆(Map K1 T,.. Map Kn T)。在映射中插入键值对既不会复制键也不会复制值,只会分配在索引中的正确位置创建新条目所需的额外堆。在多个索引中插入适当键入的相同值不应该破坏共享(即使其中一个键值)。值得在API中包装结构,以确保对值的任何后续修改都计算一次并共享,而不是为索引中的每个条目重新计算。

底线:应该可以维护多个地图,确保共享这些值,即使按键顺序是分开的。