为什么使用列表理解而不是更实用的方法,例如
map (*2) [1..5]
?
我认为列表理解语法不是很直接,需要记住,并且在 Haskell 中是多余的语法和功能,因为你可以只用列表函数做它能做的一切。
我错了吗?有没有什么事情可以用列表理解来做,而用函数式方法却做不到?
你没有错,列表理解语法不是需要。但
do
表示法(顺便说一句,它以几乎相同的方式脱糖),或者简单的列表文字,甚至字符串文字都不是。您可以随时写,而不是写
"Hello, World!"
'H':'e':'l':'l':'o':',':' ':'W':'o':'r':'l':'d':'!':[]
更进一步,您还可能会问为什么我们不只用 lambda 演算/System F 编写程序,而不是用实际的编程语言。
你大概可以明白我的意思了:
你为什么要使用列表理解
– 因为它们简洁、美观,而且很容易理解其含义。
具体来说,我认为列表推导式很好地把对快速理解最有用的信息放在前面:例如,
[x*2 | x<-[1..5]]
通过眼睛解析为
[...
好的,名单出来了[x*2 ...
好的,至少有一个条目具有 x*2
的形式(无论 x
是什么),即偶数。[x*2 |...
啊,所有条目都是偶数,在某些源上量化[x*2 | x<-...
好的,所以 x
是列表中每个条目的变化[x*2 | x<-[1..5]
对,所以具体使用的数字是[1..5]
我想说,在很多情况下,这确实是快速阅读时从最有趣到最不有趣的顺序。它基本上是从通过示例解释(或原型)您得到什么样的结果条目开始,然后再详细了解条目的不同之处。
极端相反的是命令式
forM [1..5] $ \x -> do
return $ x*2
在这里,我们从“开始一个循环”和“循环这些数字”开始,这很好,因为它概述了即将发生的事情操作性,但对“外延”的含义知之甚少。结果。然后继续定义变量x
等..
map
版本介于两者之间,具有使用无点语法的额外怪癖。各有其优点和缺点。
这三种风格都有各自的用例,具体取决于哪种情况最适合每种情况。
引入的,返回首先用 | 分隔,新术语用逗号分隔,而不是分号或换行符。这使得它们很方便。顺便说一下,列表推导式可以与其他 monad 一起使用,使用扩展名 MonadCompressives。 事后看来,我们应该将 do 块和列表推导式与一种类型的糖结合起来。我认为这两者背后的理性在于,do-blocks 首先是作为一种让新手更容易开始编写 Haskell 的方式,而列表表示法是对数学人的回应,他们希望受到集合构建表示法的启发而获得更多便利。人们往往会对糖上瘾,因此他们会要求更多。