【问题标题】:Map vs Filter over infinite lists?映射与过滤无限列表?
【发布时间】:2014-05-11 22:06:54
【问题描述】:

我正在学习 Haskell,但我遇到了一些我无法理解的东西,我找不到解释。所以,我在无限列表上测试了一些函数,看看它们是如何工作的,我发现了我想理解的 map 和 filter 之间的区别。

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..]

输出开始并且永远不会结束,直到我停止它。 Wich 是有道理的,因为列表是无限的。

但是现在如果我运行这个:

filter (==5) [1..]

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

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

【问题讨论】:

  • 你肯定看到[5 然后什么都没有?
  • 我刚刚编辑,我什至没有看到 [5
  • 我无法重现。我看到了[5
  • 那没有意义。您使用的是哪个编译器/解释器?
  • 可能是因为我使用的是tryhaskell.org。我将下载 Haskell 平台并在那里尝试!

标签: haskell


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    它与buffer settings 相关。编译时,stdinstdout 的 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.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-22
      • 2019-08-20
      • 1970-01-01
      • 2012-08-04
      • 2020-04-05
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多