0

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?

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
Tom coates
  • 53
  • 1
  • 7
  • 3
    I see that you got already some answers to your questions, but make sure to show your attempts on how you tried to solve this yourself next time - this is no "we solve your haskell homework for you"-site but a "we help you solve problems yourself"-site, make sure you put at least as much effort into posting a question as you would somebody expect to answer it – epsilonhalbe Oct 08 '17 at 22:26
  • 1
    The loop is unnecessary, because you keep overwriting `foo`: `foo = (99, 99)` alone produces the same result. – chepner Oct 09 '17 at 00:57

4 Answers4

7

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.

amalloy
  • 89,153
  • 8
  • 140
  • 205
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
2

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)]
Redu
  • 25,060
  • 6
  • 56
  • 76
1

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)]
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1

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]]
HTNW
  • 27,182
  • 1
  • 32
  • 60