习惯于条件列表理解的方法

时间:2014-04-24 13:08:33

标签: haskell list-comprehension

我刚刚开始学习Haskell,我似乎找不到有条件地创建列表的好方法。

基本上,我想要的是使用if/else进行列表理解,但没有else部分。我确信这是可能的,我想我只是在google搜索任务中使用错误的关键字。

Python中我想要Haskellize的一个非常愚蠢的例子:

[x for x in range(11) if x > 5]

在Haskell中,据我所知,我们不能像在Python示例中那样省略else块。我该怎么做这样的事情?是否存在类似 nothing 之类的东西,我可以添加到列表理解中的else - 块中,如下所示:

[if x > 5 then x else Nothing | x <- [0..10]]

我实际上遇到了Haskell中的 Nothing ,尽管我还没弄明白。它当然似乎没有做我希望的。基本上我不想在列表理解中使用else,但如果它是必要的邪恶,我想在else块中不插入任何内容。

我可以想到一堆黑客可以非常低效地获得类似的功能:

    创建后的列表
  • filter,例如filter (>5) [0..10]
  • 使用列表推导创建列表列表,我可以在else块中创建一个空列表,然后在concat中创建一个列表,例如: concat [if x > 5 then [x] else [] | x <- [0..10]]

但这些想法似乎都非常丑陋。

当然在实践中我不想创建具有这些微不足道条件的条件列表。

2 个答案:

答案 0 :(得分:21)

使用此:

Prelude> [x | x <- [0..10], x > 5]
[6,7,8,9,10]

在Haskell列表推导中,“源”表达式和所有过滤器/ ifs都是“兄弟”,即与Python不同,它们之间没有太多的语法区别。所以

<expr1> for <source_expr> if <cond_expr>

就是Haskell中的这个:

[<expr1> | <source_expr>, <cond_expr>, ...]

source_expr在Python中为x in range(0, 10)或在Haskell中为x <- [0..9]

你可以在Haskell列表理解中拥有尽可能多的“source”和“filter”表达式。

这也意味着你可以用更接近数学符号的风格写东西;考虑:

{ x : x ∈ [0, 10), x > 5 }

并且看看Haskell版本与Python版本几乎相同,后者看起来更具程序性/必要性。


这也很简单,不需要使用多个“源”表达式的其他语法/结构

Prelude> [(x, y) | x <- [0..10], y <- [10..20], y - x < 5]
[(6,10),(7,10),(7,11),(8,10),(8,11),(8,12),(9,10),(9,11),(9,12),(9,13),(10,10),(10,11),(10,12),(10,13),(10,14)]

在Python中你必须拥有看起来像嵌套列表理解的东西,但是Haskell仍然只是坚持数学方法/符号。

答案 1 :(得分:3)

在Haskell中,Python调用if的内容并不存在。对于&#34;如果没有其他&#34;要有意义,你需要一个什么样的概念&#34;什么都不做&#34;甚至意味着 - 通常,这个想法在函数式语言中没有意义,因为函数都是关于我保证你,因为你给我的任何论据我都会回复一个有用的答案 。你不能只是说,&#34;不,不想回报任何东西&#34; ... 除非没有结果恰好是返回类型的值。事实上,这是为列表提供的,这是首先考虑过滤的唯一原因。

更一般地说,&#34;虚无&#34;被一种特殊的monad捕获:the MonadPlus class。事实上,最简单的实例是您已经偶然发现的Nothing构造函数:

  

Prelude Control.Monad&gt; mzero ::也许Int   没有

您看到它的类型中有Maybe,即我们明确指出它不能保证会有结果

选择&#34;产生某种东西,或不产生&#34;在Haskell中不是if,而是guard。在monadic写作中,你的理解看起来如此:

yourList = do
   x <- [0..11]
   guard (x > 5)
   return x

实际上,列表理解[ x | x <- [0..11], x>5 ]基本上就是语法糖。

如果你不了解monad,那么

guard有点奇怪。还有另外一种功能,你经常会看到它做了非常相似的事情(虽然方式完全不同),when,这个功能通常用于&#34;执行 - 或 - 别&#39;叔如果&#34;用命令语言。