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?
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:
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 incrementborcfor a change.So you need to generate tuples in more balanced ways.
You can use, for instance, this method:
tripleNgenerates all the ordered triples with sumn. 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:
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)]