为什么要使用列表理解?

Pil*_*ful 0 haskell functional-programming list-comprehension list

为什么使用列表理解而不是更实用的方法,例如map (*2) [1..5]

我认为列表理解语法不是很直接,需要记住,并且在 Haskell 中是多余的语法和功能,因为你可以只用列表函数做它能做的一切。

我错了吗?是否有一些事情可以用列表理解来做,而用函数式方法却做不到?

lef*_*out 8

你没有错,不需要列表理解语法。但do符号(顺便说一句,以几乎相同的方式脱糖)、简单列表文字,甚至字符串文字都不是。"Hello, World!"你可以随时写而不是写

\n
       'H':'e':'l':'l':'o':',':' ':'W':'o':'r':'l':'d':'!':[]\n
Run Code Online (Sandbox Code Playgroud)\n

更进一步,您还可能会问为什么我们不只用 lambda 演算/System F 编写程序,而不是使用实际的编程语言。

\n

你可能会明白我的意思:

\n
\n

你为什么要使用列表理解

\n
\n

\xe2\x80\x93 因为它们简洁、美观,而且很容易理解其含义。

\n

具体来说,我认为列表推导式很好地把对快速理解最有用的信息放在前面:例如,[x*2 | x<-[1..5]]通过眼睛解析,例如

\n
    \n
  • [...好的,有一个列表即将出现
  • \n
  • [x*2 ...好的,至少有一个条目具有以下形式x*2(无论x是什么),即偶数。
  • \n
  • [x*2 |...啊,所有条目都是偶数,通过某个源进行量化
  • \n
  • [x*2 | x<-...好的,x列表中每个条目的变化也是如此
  • \n
  • [x*2 | x<-[1..5]是的,所以使用的具体数字将是[1..5]
  • \n
\n

我想说,在很多情况下,这确实是快速阅读时从最有趣到最不有趣的大致顺序。它基本上首先通过示例(或原型)解释您得到的结果条目类型,然后再详细了解条目的不同之处。

\n

极端相反的是命令式

\n
forM [1..5] $ \\x -> do\n   return $ x*2\n
Run Code Online (Sandbox Code Playgroud)\n

在这里,我们从“开始一个循环”和“循环这些数字”开始,这很好,因为它给出了将要发生的操作的概述,但对结果的外延含义知之甚少。然后继续定义变量x等。

\n

map版本介于两者之间,具有使用无点语法的额外怪癖。其中有其自身的优点和缺点。

\n

这三种风格都有各自的用例,具体取决于哪种情况最适合哪种风格。

\n

  • 为了添加这个好的答案,这里有一个示例,其中列表理解(IMO)比更“标准”的组合器更具可读性:/sf/answers/5229317691/ (2认同)
  • @Piliponful 不,列表理解是合元糖。他们不提供任何你不能没有的东西。它们始终可以转换为利用“concatMap”等标准函数的代码。它们的语义在 Haskell Report 中给出了[这样的代码转换](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-420003.11)。 (2认同)