地图与过滤无限列表?

时间:2014-05-11 22:06:55

标签: haskell

我正在学习Haskell,而且我遇到了一些我无法理解的东西,而且我无法找到解释。所以,我在无限列表上测试了一些函数,看看它们是如何工作的,我发现了我想要理解的地图和滤镜之间的差异。

Prelude.map定义:

map _ []     = []
map f (x:xs) = f x : map f xs

Prelude.filter定义:

filter _pred []    = []
filter pred (x:xs)
  | pred x         = x : filter pred xs
  | otherwise      = filter pred xs

如果我这样做:

map (==5) [1..]

输出开始,它永远不会结束,直到我停止它。因为列表是无限的,所以很有意义。

但现在如果我这样做:

filter (==5) [1..]

我什么也没看到,甚至没有[5,。 这也是有道理的,因为列表也是无限的,但我想了解这是什么区别beetwen map和filter。 谢谢你,对不起我的英文!

编辑:我使用的是tryhaskell.org,这就是问题!

2 个答案:

答案 0 :(得分:8)

正如评论中所发现的,这是由于使用了Try Haskell。从实验开始,在结束并向您发送结果之前,它似乎将等待程序终止,经过3秒或产生1024个字符的输出。不幸的是,filter (==5) [1..]只会生成两个字符([5),不符合1024个字符的限制,由于某种原因,Try Haskell不会向您发送[5。在真正的GHCi中运行它应该可以正常工作。

答案 1 :(得分:3)

它与buffer settings有关。编译时,默认情况下, stdin stdout 的BufferMode通常设置为LineBuffering,仅在换行,缓冲区溢出或手动刷新时打印。

GHCi的BufferMode设置为NoBuffering¹,它将立即打印您的结果。

如果是LineBuffering:

  • map (==5) [1..]打印其结果,因为它的大输出会导致大量缓冲区溢出。
  • filter (==5) [1..]从不填充缓冲区或写入换行符。所以它不打印。
如果可能的话,

¹。 NoBuffering for stdin might not work on Windows cmd, when compiled with GHC.