在Haskell的O(1)时间内获得Ix范围的中间值

时间:2010-09-08 14:22:24

标签: arrays haskell functional-programming complexity-theory time-complexity

我在Haskell中使用this代码kata,我在主题中遇到了问题。

找到索引为单个数值的数组的中点是微不足道的,但Haskell的数组索引可以是Ix类型类的任何实例,包括例如,卡是的元组(Int,Word,Card) Ix的一个实例,但不是Num的实例。

获取数组中点的一种方法是查询其长度,查询索引列表,并删除该列表的一半,但这需要O(n)时间。

有没有人知道在常规时间内进行索引的方法?我觉得应该有一个,因为Ix范围应该用整数范围生成。

1 个答案:

答案 0 :(得分:4)

Ix类型类只需要从类型i的值注入到Int的值。 indexrange一起可以为我们提供逆映射:

index' :: (Ix i) => (i, i) -> Int -> i
index' b x = range b ! x

正如您所看到的,index'至少在线性时间内进行评估。我们也无法知道range b的工作时间。它以用户在实例定义中定义的方式进行评估。因此,当且仅当我们有某种index'在恒定时间内工作时,才能进行所需的优化(获取数组的中点)。由于Ix类型类没有为我们提供从Inti的恒定时间映射,我们应该向用户询问。考虑下一个代码:

midpoint :: (Ix j) => (Int -> j) -> Array j e -> e
midpoint f a = a ! f middle
               where middle = rangeSize (bounds a) `div` 2

现在,采用数组中点的复杂性取决于用户定义的f的复杂性。因此,如果我们的索引类型i的值可以在Int值的恒定时间内评估,反之亦然 - 我们会在恒定时间内获得中点。

还要考虑来自ixmap的{​​{1}}函数:

Data.Ix