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?

2
  • 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 Commented Oct 8, 2017 at 22:26
  • 1
    The loop is unnecessary, because you keep overwriting foo: foo = (99, 99) alone produces the same result. Commented Oct 9, 2017 at 0:57

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

Comments

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)]

3 Comments

Doesn't remove duplicates. You'd have to use monads instead.
...or repair afterwards, i.e. filter (uncurry (<=)) $ (,) <$> [0..2] <*> [0..3].
@leftaroundabout Yes that's possible but then it turns out to be a little wasteful i suppose. I guess this approach is not right for the given case. It's my oversight.
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]]

Comments

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)]

1 Comment

Mind the direction of your comparisons

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.