【问题标题】:haskell - let/where equivalent within list comprehension?haskell - 让/在列表理解中等效?
【发布时间】:2018-03-24 02:26:32
【问题描述】:

有没有办法使用let,where 或以其他方式在列表推导中定义子表达式,以便它可以在术语和约束中使用?

根据我的实验,以下工作:

[let x = i*i in x | i<-[1..10], i*i > 20]   --good
[i*i | i<-[1..10], let x=i*i in x > 20]     --good

但这些不属于范围:

[let x = i*i in x | i<-[1..10], x > 20]  -- 'x' not in scope error
let x = i*i in [x | i<-[1..10], x > 20]  -- 'i' not in scope error
[x | i<-[1..10], x > 20] where x = i*i   --parse error on 'where'

所以let 在一个地方工作,但不能同时工作!

我发现使其工作的唯一方法(即避免重复的表达式和可能的评估)是添加一个愚蠢的单例列表,就像我在这里所做的那样,使用x&lt;-[cat i [1..k] 作为列表理解的约束:

> let cat x l = foldl1 (++) $ map show [x*i | i<-l]
maximum [x| i<-[1..9999], k<-[2..div 10 $ length $ show i], x<-[cat i [1..k]], sort x == "123456789"]
"932718654"

或者,继续上面的简单示例,

[x | i<-[0..10], x<-[i*i], x > 20] --works

这似乎有点傻,并且有点缺乏清晰度,但它似乎并没有太低效。不过,如果letwhere 在整个理解范围内工作,那就太好了。这个可以吗?

【问题讨论】:

  • 您的第二个示例[x | i&lt;-[1..10], let x=i*i in x &gt; 20] 无法编译;你的意思是[i*i | i&lt;-[1..10], let x=i*i in x &gt; 20]
  • 好的,谢谢。如果第一个工作我会回答我自己的问题
  • 欧拉项目要求您,而不是发布问题的解决方案。我会鼓励您用其他东西替换欧拉示例。

标签: haskell functional-programming list-comprehension


【解决方案1】:

你这样写:

[x | i <- [0..10], let x = i*i, x > 20]

注意没有in。您可以在术语中引用x,以及let 之后的任何约束。 let的这种形式对应do-notation中的那一种:

do i <- [0..10]
   let x = i*i
   guard (x > 20)
   return x

这里x 的范围是从letdo 块的末尾。

【讨论】:

  • 谢谢,我知道一定有什么。如果这只是语言中的一些漏洞,我会非常失望=P
  • @jon_darkstar,哦,别上当了。语言中有许多巨大的漏洞。例如,Applicative 应该填写的那个。
【解决方案2】:

你几乎拥有它;你可以简单地写[x | i &lt;- [0..10], let x = i*i, x &gt; 20](注意,而不是in)。它与do-notation 非常相似(实际上,您可以改用do-notation,最近的GHC 扩展使您可以对任意monad 使用列表推导)。如果你好奇,你可以找到in the Haskell 98 report的语法:

aexp -> [ exp | qual_1 , ... , qual_n ] (list comprehension, n >= 1)
qual -> pat <- exp                      (generator)
     |  let decls                       (local declaration)
     |  exp                             (guard)

如您所见,有效的限定符之一是 let decls,这正是您想要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多