How to use Haskells laziness when finding right triangles

haskell, lazy-evaluation

Solution

Well, the laziness isn't the problem here. It's the order in which you're iterating the variables in the list.

Basically what happens is:

- c is bound to 1

- b is bound to 1

- a is bound to 1

- Equation is checked

- a is bound to 2

- Equation is checked

- a is bound to 3

- Equation is checked

and it goes on forever.

So the generator keeps on iterating and binding values for `a`, because it doesn't know that you need to stop and also increment `b` or `c` for a change.

So you need to generate tuples in more balanced ways.

You can use, for instance, this method:

triplesN :: Int -> [(Int, Int, Int)]
triplesN n = [(i, j, n - i - j) | i <- [1..n - 2], 
                                  j <- [1..n - i - 1], i>=j, 
                                  let k = n - i - j,   j>=k]

isTriangle (a, b, c) = a^2 == b^2 + c^2

triangles = filter isTriangle $ concatMap triplesN [1..]

`tripleN` generates all the ordered triples with sum `n`. By mapping this function over all the natural numbers we actually get the stream of all ordered pairs. And finally, we filter only those triples that are triangles.

By doing:

take 10 triangles

we get:

`[(5,4,3),(10,8,6),(13,12,5),(15,12,9),(17,15,8),(20,16,12),(25,24,7),(25,20,15),(26,24,10),(29,21,20)]`

Problem

I'm following the (excellent) Haskell tutorial at http://learnyouahaskell.com/starting-out and am trying out the right triangle example: ``` > let triangles = [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2] ``` running this I get, as expected: ``` > triangles [(4,3,5),(3,4,5),(8,6,10),(6,8,10)] ``` Now, I'd like to try using infinite lists instead: ``` > let triangles = [(a,b,c) | c <- [1..], b <- [1..], a <- [1..], a^2 + b^2 == c^2] ``` But when I try it, like: ``` > take 2 triangles ``` ...the programs just runs and runs with no output. What am I doing wrong? I thought Haskells laziness would cause it to find the two first triangles and then halt?

Original source