Opened 8 years ago

Closed 7 years ago

#3380 closed feature request (wontfix)

[Patch] Support implicit concatenation in list comprehensions

Reported by: batterseapower Owned by:
Priority: normal Milestone:
Component: Compiler Version: 6.10.4
Keywords: Cc: ndmitchell@…, batterseapower@…, koen@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Using the -XImplicitConcatListComp option turns on implicit concatenation in list comprehensions. What this means is that you can write several things separated by commas in the "body" of a list comprehension, like so

[x, x | x <- [1..10], x `mod` 2 == 0]

This program produces the following output

[2, 2, 4, 4, 6, 6, 8, 8]

The effect is the same as if you had written

concat [[x, x] | x &lt;- [1..10], x `mod` 2 == 0]

but more concise, and more likely to be optimised well by the compiler.

NB: this was originally proposed in the SQL-like list comprehensions paper.

Attachments (2)

ImplicitConcatListComp-compiler.patch (48.5 KB) - added by batterseapower 8 years ago.
ImplicitConcatListComp-testsuite.patch (5.6 KB) - added by batterseapower 8 years ago.

Download all attachments as: .zip

Change History (13)

Changed 8 years ago by batterseapower

Changed 8 years ago by batterseapower

comment:1 Changed 8 years ago by batterseapower

Cc: ndmitchell@… batterseapower@… added

comment:2 Changed 8 years ago by batterseapower

NB: this generalises to instances of MonadPlus, but I can't think of a nice-looking syntax.

[e1, e2 | qs]
= concat [[e1, e2] | qs]
= join [return e1 `mplus` return e2 | qs]

This is pretty easy to implement as long as you can come up with the syntax.

comment:3 Changed 8 years ago by ross

So this is a slightly shorter way of writing

[x' | x <- [1..10], x `mod` 2 == 0, x' <- [x, x]]

comment:4 Changed 8 years ago by batterseapower

Yes, though the code generated by this patch may be /slightly/ better than for your version if you have RULES or foldr/buildable list literals turned off. The "killer app" that made me implement this was to support the following idiom:

system "foo" $
  ["foo" | fooing_enabled] ++
  ["bar" | baring_enabled]

If you want to turn on two options when baring_enabled is on then you can now write:

system "foo" $
  ["foo" | fooing_enabled] ++
  ["bar1", "bar2" | baring_enabled]

Which seems quite slick. It's a rather nice interpretation of some otherwise unused syntax IMHO.

comment:5 Changed 8 years ago by simonpj

Cc: koen@… added
difficulty: Unknown

Thanks for trying this out. I'm adding Koen to the cc list since he suggested the idea originally.

Frankly, I'm unsure whether it's a feature that pays its way. It uses syntactic space, which is good, but it's one more thing to maintain and explain. It's not a big deal, but I'd like to hear some more people saying "oh yes I want this" before committing to it forever.

Max: one way to get such expressions of support would be to describe the feature (linking to this ticket) in a message to Haskell Cafe, and encourage people to add use cases.

Does anyone else have an opinion, especially Koen?


comment:6 Changed 8 years ago by igloo

I have no net opinion either way. On the one hand, it would be nice to be able to do it, but on the flipside, I can imagine people getting confused if they don't notice that there isn't an extra pair of square brackets.

A quick grep finds some cases where this could be used in the GHC sources:

./main/DriverPipeline.hs:    let pkg_framework_opts = concat [ ["-framework", fw] | fw <- pkg_frameworks ]
./main/DriverPipeline.hs:        framework_opts = concat [ ["-framework", fw] | fw <- reverse frameworks ]
./main/GHC.hs:    concat [ [(m,True), (m,False)] | m <- ms_home_srcimps s ] 
./rename/RnNames.lhs:        ; addUsedRdrNames (concat [ [mkRdrQual mod occ, mkRdrUnqual occ]

comment:7 Changed 8 years ago by batterseapower

OK, I've started a thread on the cafe:

comment:8 Changed 8 years ago by duncan

I support this extension. It's exactly the syntax I have often wished we had. The case where I have wished we had this is the same as cited above, namely building lists of command line flags (there's a lot of that in Cabal).

comment:9 Changed 8 years ago by igloo

Milestone: 6.14.1

Need to work out what the consensus of the thread was.

comment:10 Changed 8 years ago by simonpj

Milestone: 6.14.1_|_

I've just read the thread. My impression is that support is luke-warm at best.

I'll milestone this as "_|_" so that it's not forgotten, but meanwhile I am disinclined to take action.

(Many responders were enthusiastic about tuple sections, which are indeed now implemented. Thanks for doing that.)


comment:11 Changed 7 years ago by batterseapower

Resolution: wontfix
Status: newclosed
Type of failure: None/Unknown

Noone likes this, let's not clutter up the issue tracker :-)

Note: See TracTickets for help on using tickets.