Question

So, for example, say I had a list of numbers and I wanted to create a list that contained each number multiplied by 2 and 3. Is there any way to do something like the following, but get back a single list of numbers instead of a list of lists of numbers?

mult_nums = [ [(n*2),(n*3)] | n <- [1..5]] 
-- this returns [[2,3],[4,6],[6,9],[8,12],[10,15]]
-- but we want [2,3,4,6,6,9,8,12,10,15]
Was it helpful?

Solution

you could use concat.

concat [ [(n*2),(n*3)] | n <- [1..5]] 
output: [2,3,4,6,6,9,8,12,10,15]

OTHER TIPS

I find that extending the list comprehension makes this easier to read:

[ m | n <- [1..5], m <- [2*n,3*n] ]

It might be helpful to examine exactly what this does, and how it relates to other solutions. Let's define it as a function:

mult lst = [ m | n <- lst, m <- [2*n,3*n] ]

After a fashion, this desugars to

mult' lst = 
    concatMap (\n -> concatMap (\m -> [m]) [2*n,3*n]) lst

The expression concatMap (\m -> [m]) is wrapping m up in a list in order to immediately flatten it—it is equivalent to map id.

Compare this to @FunctorSalad's answer:

mult1 lst = concatMap (\n -> [n*2,n*3]) lst

We've optimized away concatMap (\m -> [m]).

Now @vili's answer:

mult2 lst = concat [ [(n*2),(n*3)] | n <- lst]

This desugars to:

mult2' lst = concat (concatMap (\n -> [[2*n,3*n]]) lst)

As in the first solution above, we are unnecessarily creating a list of lists that we have to concat away.

I don't think there is a solution that uses list comprehensions, but desugars to mult1. My intuition is that Haskell compilers are generally clever enough that this wouldn't matter (or, alternatively, that unnecessary concats are cheap due to lazy evaluation (whereas they're lethal in eager languages)).

In some similar cases concatMap can also be convenient, though here it doesn't change much:

concatMap (\n -> [n*2,n*3]) [1..5]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top