Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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 - Fatal编程技术网

Haskell 哈斯克尔循环函数

Haskell 哈斯克尔循环函数,haskell,Haskell,循环的代码如下所示 cycle :: [a] -> [a] cycle [] = errorEmptyList "cycle" cycle xs = xs' where xs' = xs ++ xs' 如果能解释一下最后一行是如何工作的,我将不胜感激。我觉得它会进入一个无限的递归,而不会返回,或者我应该说,不会在屏幕上打印任何东西。我猜我的直觉是错误的。一个列表,基本上和Haskell中的其他

循环的代码如下所示

cycle                   :: [a] -> [a]
cycle []                = errorEmptyList "cycle"
cycle xs                = xs' where xs' = xs ++ xs'

如果能解释一下最后一行是如何工作的,我将不胜感激。我觉得它会进入一个无限的递归,而不会返回,或者我应该说,不会在屏幕上打印任何东西。我猜我的直觉是错误的。

一个列表,基本上和Haskell中的其他东西一样,都是懒散地评估的

粗略地说,要进行OOP类比,可以将列表看作一种“迭代器对象”。当被查询时,它会报告是否有下一个元素,如果有,什么是这样的元素,列表的尾部是什么(这是另一个“迭代器对象”)

定义为

xs = 1 : xs
不会导致不终止。它对应于一个“迭代器对象”
o
,当被查询时,该对象回答:“下一个元素是
1
,可以使用
o
”查询列表的其余部分。”。基本上,它会自动返回

这和一个列表没有什么不同,它的尾部有一个指向列表本身的“指针”:一个循环列表。这需要一个恒定的空间量

添加
++
的效果相同:

xs = [1] ++ xs
与上一个列表相同

在您的代码中

where xs' = xs ++ xs'

创建一个以
xs
开头的列表,然后继续列表本身
xs'
。在操作上,它是一个“迭代器对象”
o
,一个接一个地返回
xs
的元素,当返回
xs
的最后一个元素时,它与“您可以在
o
处查询列表的其余部分”配对。同样是一个返回指针,它构建了一种循环列表。

让我们分别取出最后一行:

cycle xs                = xs' where xs' = xs ++ xs'
现在,让我们试着减少它:

cycle xs                = xs ++ (xs ++ (xs ++ (xs ++ ...)))
你可以看到它无限扩展。但请注意,这并不是Haskell中表达式缩减的方式。表达式将减少到需要时。因此,让我们从
cycle
函数中获取一些值:

ghci > take 1 $ cycle [1..]
[1]
这就是
take
功能的实现方式:

take n _      | n <= 0 =  []
take _ []              =  []
take n (x:xs)          =  x : take (n-1) xs
您可以在ghci中进行测试:

ghci > take 1 $ cycle [1..]
^CInterrupted.

嗯,
++
是惰性地执行的。那么为什么GHCI不断地打印列表来评估它,例如
xs=[1]
<代码>xs'=[1]++(xs++xs')=[1]+([1]+(xs++xs')=…
ghci > take 1 $ cycle [1..]
^CInterrupted.