I'm trying to learn Haskell and comprehension lists but cannot find solution on this:
mylist = [x*y | x <- [1..], y <- [1..]]
After my trials the result is something like this
mylist = [1,2,3,4,5,...]
because in list comprehensions, x
takes the value 1
,and then y
changes value repeatedly.
But my goal is to achieve a different assignment so as to have the following result:
mylist = [1,2,2,4,3,3,6.....]
I mean i want the combinations being mixed and not each one apart,because I have a serious problem to have the suitable result.
I will give a more specific example.
I want a list that will have all numbers of this form:
num = 2^x * 3^y
x
and y
must take all values >= 0
.
My approach is the following:
powers = [2^x * 3^y | x <- [0..], y <- [0..]]
But in this way I only take powers of 3, because x
is constantly 0.
I tried this one
multiples = nub (merge (<=) powers2 powers3)
powers3 = [2^x * 3^y | x <- [0..], y <- [0..]]
powers2 = [2^x * 3^y | y <- [0..], x <- [0..]]
so as to merge the different ones but again,the values 6,12,etc. are missing - the result is this:
mylist = [1,2,3,4,8,9,16,27,32,64,81...]
The code that you show,
is equivalent to
so you only produce the powers of 2 and 3, without any mixed multiples. As such, there are guaranteed to be no duplicates in the stream, and the
nub
was not necessary. And of course it's incomplete.But let's look at it at another angle. It was proposed in the comments to create a 2D grid out of these numbers:
Now we're getting somewhere. At least now none are skipped. We just need to understand how to join them into one sorted, increasing stream of numbers. Simple
concat
of course won't do. We need to merge them in order. A well-known functionmerge
does that, provided the arguments are already ordered, increasing lists.Each row produced is already in increasing order, but there are infinitely many of them. Never fear,
foldr
can do it. We defineHere it is a little bit tricky. If we define
g = merge
, we'll have a run-away recursion, because eachmerge
will want to know the head element of its "right" (second) argument stream.To prevent that, we produce the leftmost element right away.
And that's that.