Reputation: 53
I need to do the following in Haskell and can't think of the correct method to do it:
for (int i=0; i<100; i++)
for (int a=0; a<100; a++)
foo = (i, a);
I also don't want 'duplicates' returned so there's not both (1, 50) and (50, 1). Any ideas on how to do this?
Upvotes: 0
Views: 354
Reputation: 477686
Well first of all if you do not want duplicates, you can add the constraint i <= a
. Or you can thus rewrite your code like:
for (int i=0; i<100; i++)
for (int a=i; a<100; a++)
foo = (i, a);
Next we can use list comprehension for this:
[(i,a) | i <- [0..99], a <- [i..99]]
So we let i
iterate over 0..99
(both inclusive), and a
over i..99
. If we take smaller bounds (6 instead of 99) we obtain:
Prelude> [(i,a) | i <- [0..6], a <- [i..6]]
[(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,2),(2,3),(2,4),(2,5),(2,6),(3,3),(3,4),(3,5),(3,6),(4,4),(4,5),(4,6),(5,5),(5,6),(6,6)]
Upvotes: 1
Reputation: 74244
You can use list comprehensions:
foo :: [(Int, Int)]
foo = [(i, a) | i <- [0..99], a <- [i..99]]
Note that there's no mutation in Haskell. Hence, you can't change the value of foo
. That's why I made it into a list instead.
Upvotes: 7
Reputation: 26201
You may also use applicative functors and simply do like this;
Prelude> (,) <$> [0..2] <*> [0..3]
[(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3)]
Upvotes: 2
Reputation: 29193
If you don't want duplicates, then the loop is really:
for(int i = 0; i < 100; i++)
for(int j = i; j < 100; j++)
something(i, j);
Which can be made into Haskell as any of
-- raw binds
[0..99] >>= \i ->
[i..99] >>= \j ->
return $ something i j
-- do-notation
do i <- [0..99]
j <- [i..99]
return $ something i j
-- list comprehension
[ something i j | i <- [0..99], j <- [i..99]]
Upvotes: 1