haskell - 让/在列表理解中等效吗?

发布于 2024-11-08 03:23:04 字数 1089 浏览 1 评论 0原文

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

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

[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<-[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 能够在整个理解过程中发挥作用,那就太好了。这可以做到吗?

Is there a way to use let,where or otherwise define sub-expressions in a list comprehension so that it can be used both in the term and constraint?

From my experimenting, the following work:

[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

But these do not bc of scope:

[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'

So let works in one place or the other, but not both together!

The only way I've found to make it work (that is, avoid repeated expressions and possibly evaluations) is to add a silly singleton-list as I did here with x<-[cat i [1..k] as a constraint to the list comprehension:

> 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"

Or, contunuing the trivial example above,

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

This seems a little silly, and is slightly lacking in clarity, tho it doesn't seem too inefficient. Still, it would be nice if let or where worked across the whole comprehension. Can this be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩动你心 2024-11-15 03:23:04

你可以这样写:

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

注意没有in。您可以在该术语以及 let 后面的任何约束中引用 x。这种形式的 let 对应于 do 表示法中的形式:

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

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

You write it like this:

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

Notice there is no in. You can refer to x in both the term, and any constraints following the let. This form of let corresponds to the one in do-notation:

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

Here x is in scope from the let to the end of the do-block.

风吹过旳痕迹 2024-11-15 03:23:04

你几乎已经拥有它了;你可以简单地写[x | i <- [0..10],设 x = i*i,x > 20](注意 , 而不是 in)。它与 do 表示法非常相似(事实上,您可以使用 do 表示法,最近的 GHC 扩展使您能够对任意 monad 使用列表推导式)。如果您好奇,可以在 Haskell 98 报告中找到语法

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

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

You almost had it; you can simply write [x | i <- [0..10], let x = i*i, x > 20] (note the , instead of in). It's very similar to do-notation (in fact, you can use do-notation instead, and a recent GHC extension enables you to use list comprehensions for arbitrary monads). If you're curious, you can find the syntax 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)

As you can see, one of the valid qualifiers is let decls, which is exactly what you wanted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文