Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么我的函数不能处理无限列表?_Haskell_Lazy Evaluation - Fatal编程技术网

Haskell 为什么我的函数不能处理无限列表?

Haskell 为什么我的函数不能处理无限列表?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,我试图学习haskell并实现一个函数conseq,该函数将返回大小为n的连续元素列表 conseq :: Int -> [Int] -> [[Int]] conseq n x | n == length(x) = [x] | n > length(x) = [x] | otherwise = [take n x] ++ (conseq n (drop 1 x)) 这是正确的 > take 5 $ conseq 2 [1..10]

我试图学习haskell并实现一个函数
conseq
,该函数将返回大小为n的连续元素列表

conseq :: Int -> [Int] -> [[Int]]
conseq n x 
      | n == length(x) = [x]
      | n > length(x) = [x]
      | otherwise = [take n x] ++ (conseq n (drop 1 x))
这是正确的

> take 5 $ conseq 2 [1..10]  
[[1,2],[2,3],[3,4],[4,5],[5,6]]
但是,如果我通过
[1..]
而不是
[1..10]
,程序就会陷入无限循环

据我所知,haskell有懒惰的评估,所以我应该仍然能够得到相同的结果,对吗?它是
长度
?当长度大于
n
时,前两个条件是否应立即计算为false


我误解了什么?

函数做的第一件事是计算
长度(x)
,这样它就知道是否应该返回
[x]
[x]
,或者
[take nx]++(conseq n(drop 1x))


length
统计列表中的元素数-所有元素。如果你要求一个无限列表的长度,它永远不会完成计数。

使用
长度
不是一个好主意的主要原因之一是,当它必须在一个无限列表上求值时,它将陷入无限循环

但好消息是,我们不需要
长度
。这也会使时间复杂性变得更糟。我们可以使用两个枚举数,一个比另一个提前n-1个位置。如果此枚举数到达列表的末尾,则我们知道第一个枚举数仍有n-1个元素,因此我们可以停止生成值:

conseq :: Int -> [a] -> [[a]]
conseq n ys = go (drop (n-1) ys) ys
    where go [] _ = []
          go (_:as) ba@(~(_:bs)) = take n ba : go as bs

什么是
length(x)
,其中
x==[1..]
?是不是
length
没有被惰性地评估?那么,你如何惰性地评估它呢?如果不知道此列表的长度,则无法继续执行,因此必须立即计算它。我不完全确定though@TessaAltman:所有内容都是惰性评估的,但当需要时,会对其进行评估,然后
length
陷入无限循环。如果
length
返回类似于Peano数的值,并且如果对Peano数的比较是延迟实现的,则可以使用
n>length x
避免无限循环。但是使用
Int
和内置的
length
,情况就不是这样了。
~ba@(:bs)
到底在做什么?我假设
(:bs)
正在删除列表的标题,然后将
bs
设置为正常模式匹配的其余部分,但我没有遇到
~
@
符号before@mattematt:
@
是as模式(),
~
用于无可辩驳的模式
Prelude> conseq 3 [1 ..]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10],[9,10,11],[10,11,12],[11,12,13],[12,13,14],[13,14,15],[14,15,16],[15,16,17],[16,17,18],[17,18,19],[18,19,20],[19,20,21],[20,21,22],[21,22,23],[22,23,24],[23,24,25],[24,25,26],[25,26,27],…
Prelude> conseq 3 [1 .. 4]
[[1,2,3],[2,3,4]]