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.