2014-01-28 61 views
4

我刚刚开始学习Haskell,并开始玩弄无限列表和懒惰评估的想法。我构建了一个无限列表,并尝试使用!!运算符访问非常非常非常遥远的索引处的元素。问题是,对于!!操作类型签名如下:(!!)运算符溢出整数

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

这意味着它需要一个Int作为索引检索从列表中该元素。

现在,每当我尝试将索引溢出Int并因此变为负数时发生问题。然后什么才是适当的Haskell这样做的方式?

+6

在任何现代系统上,无论如何这将是非常不切实际的:'maxBound :: Int'在CPU时钟周期中大约是30年。直到你得到你的结果,我们才有可能拥有所有的128位'Int',并且你必须等待比宇宙的年龄更长的时间,直到你发生溢出为止...... – leftaroundabout

+0

@leftaroundabout你会惊讶于发现情况并非如此。下面的解决方案对我来说工作得很好。 –

+0

在32位平台上,你当然很快就会受到'Int'的限制。在64位,没办法。 (这些都不是Haskell标准中规定的,所以即使所有的平台都有256位,你的问题也是有效的,但是'Prelude。!!'有这个签名是完全可以的,这就是我的观点,特别是任何有限列表这完全存储在内存中,需要适应虚拟内存,这基本上是由'Int'来实现的,所以使用'Integer'有点疯狂。) – leftaroundabout

回答

8

Data.List.genericIndex支持使用所有整数索引,所以你可以,如果你想使用的整数。

1

自己与Integer,而不是Int实现!!

(!!!) :: [a] -> Integer -> a 
xs  !!! n | n < 0 = error "negative index" 
[]  !!! _   = error "index too large" 
(x:_) !!! 0   = x 
(_:xs) !!! n   = xs !!! (pred n)