I have a quick question about Haskell. I’ve been following Learn You a Haskell, and am just a bit confused as to the execution order / logic of the following snippet, used to calculate the side lengths of a triangle, when all sides are equal to or less than 10 and the total perimeter of the triangle is 24:
[(a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c==24]
The part that is confusing to me is the upper expansion bound on the b and a binding. From what I gather, the ..c and ..b are used to remove additional permutations (combinations?) of the same set of triangle sides.
When I run it with the ..c/b, I get the answer:
[(6,8,10)]
When I don’t have the ..c/b:
[(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2, a+b+c==24]
as I didn’t when I initially typed it in, I got:
[(8,6,10),(6,8,10)]
Which is obviously representative of the same triangle, save for the a and b values have been swapped.
So, can someone walk me through the logic / execution / evaluation of what’s going on here?
The original version considers all triplets (a,b,c) where c is a number between 1 and 10, b is a number between 1 and c and a is a number between 1 and b. (6,8,10) fits that criteria, (8,6,10) doesn’t (because here a is 8 and b is 6, so a isn’t between 0 and 6).
In your version you consider all triplets (a,b,c) where a, b and c are between 1 and 10. You make no restrictions on how a, b and c relate to each other, so (8, 6, 10) is not excluded since all numbers in it are indeed between 1 and 10.
If you think of it in terms of imperative for-loops, your version does this:
while the original version does this: