在Haskell中,使用takeWhile或使用“常规"标记之间有什么区别?列表理解中的不平等? [英] In Haskell, what's the difference between using takeWhile or using a "regular" inequality in this list comprehension?

查看:77
本文介绍了在Haskell中,使用takeWhile或使用“常规"标记之间有什么区别?列表理解中的不平等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我学习Haskell(非常好),而我正在做的许多不同工作之一就是在我要测试自己的能力时,尝试解决一些Euler项目的问题.

I'm trying to learn me a Haskell (for great good), and one of the many different things I'm doing is trying to tackle some Project Euler problems as I'm going along to test my mettle.

在处理一些基于Fibonacci的问题时,我偶然发现并开始研究Fibonacci序列的递归无限列表版本:

In doing some of the Fibonacci based problems, I stumbled on and started playing around with the recursive infinite list version of the Fibonacci sequence:

fibs = 1 : 2 : zipWith (+) fibs (tail fibs)

对于PE问题之一,我需要提取甚至小于4,000,000的斐波那契数的子序列.我决定通过列表理解来做到这一点,在玩代码的过程中,我偶然发现了一些我不太了解的东西.我假设这是我对Haskell的惰性评估方案的不完全了解,这使事情变得复杂了.

For one of the PE problems, I needed to extract the subsequence of even Fibonacci numbers less than 4,000,000. I decided to do this with a list comprehension, and in my playing around with the code I stumbled on to something that I don't quite understand; I'm assuming that it's my weak grasp on Haskell's lazy evaluation scheme that's complicating things.

以下理解工作正常:

[x | x <- takeWhile (<= 4000000) fibs, even x]

下一个理解将永远旋转;因此,我进行了一次检查,使输出返回到stdout,并在正确的位置停止输出时,似乎一直在继续评估递归定义的列表,直到达到上限后才结束.指示列表中的最后一项用逗号打印但没有其他列表项或右方括号的事实:

The next comprehension spins forever; so I went through and had the output returned to stdout and while it stops at the correct place, it just seems to continue evaluating the recursively defined list forever without finishing after reaching the capped value; indicative of the fact that the last item in the list is printed with a comma but no further list items or closing square bracket are present:

[x | x <- fibs, x <= 4000000, even x]

那么,在无限列表中能很好发挥作用的各种功能所使用的秘密调味料到底是什么?

So what exactly is the secret sauce used by the various functions that do play well with infinite lists?

推荐答案

函数takeWhile不断获取输入列表的元素,直到到达满足谓词的第一个元素为止,然后停止.只要存在至少一个不满足谓词的元素,takeWhile就会将无限列表转换为有限列表.

The function takeWhile keeps taking elements of the input list until it reaches the first element that doesn't satisfy the predicate, and then it stops. As long as there is at least one element that doesn't satisfy the predicate, takeWhile turns infinite lists into finite lists.

您的第一个表情说

继续获取此无限列表中的元素,直到找到大于4,000,000的元素,然后停止.如果输出中的每个元素都是偶数,则将其包括在内.

Keep taking elements of this infinite list until you find one greater than 4,000,000 and then stop. Include each element in the output if it's even.

第二个表达式说

保留此无限列表的元素.如果每个元素小于或等于4,000,000,并且为偶数,则将其包含在输出中.

Keep taking elements of this infinite list. Include each element in the output if it's less than or equal 4,000,000 and it's even.

当您观察到一个永久挂起的输出时,该函数正忙于生成更多的斐波那契数,并检查它们是否小于或等于4,000,000.它们都不是,这就是为什么什么都没有打印到屏幕上的原因,但是该函数无法知道在列表的下方不会遇到少量数字,因此必须进行检查.

When you observe an output that hangs forever, the function is busily generating more fibonacci numbers and checking to see if they're less than or equal 4,000,000. None of them are, which is why nothing is printed to the screen, but the function has no way of knowing that it's not going to encounter a small number a bit further down the list, so it has to keep checking.

这篇关于在Haskell中,使用takeWhile或使用“常规"标记之间有什么区别?列表理解中的不平等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆