Search code examples
listhaskellinfinitepythagorean

Infinite list not being terminated after appropriate value is found.


I have written the following function that returns an infinite list of 3-tuple members, (a, b, c) according to the definition of a Pythagorean triples: a^2 + b^2 = c^2. I need to be able to check if a given tuple (a, b, c) is a valid Pythagorean triple. The way I do this is by generating an infinite list of tuples by means of the function and I pass this list to elem along with the 3-tuple I want to check.

However, this does not terminate when it matches my 3-tuple to a member of the infinite list.

Code:

pythagoreanTriples::[(Integer, Integer, Integer)]
pythagoreanTriples = [(a, b, c) | a <- [2..], b <- [a+1..], 
                                  c <- [b+1..], a*a + b*b == c*c ]
main = do
print $ elem (30, 72, 78) (pythagoreanTriples)

I know the logic is correct, because I have tried modifying the above function to produce an finite list and the logic works very nicely:

pythagoreanTriples n = [(a, b, c) | a <- [2..n], b <- [a+1..n], 
                                    c <- [b+1..n], a*a + b*b == c*c ]

main = do
print $ elem (30, 72, 78) (pythagoreanTriples 100)

However, it must be done with an infinite list. Please suggest to me how I can make it work. Thanks.


Solution

  • Start with your finite code,

    pythagoreanTriples n = [(a, b, c) | a <- [2..n], b <- [a+1..n], 
                                        c <- [b+1..n], a*a + b*b == c*c ]
    

    and simply make it work for any n from 1 and up:

    pythagoreanTriples   = [(a, b, c) | n <- [1..],
                                        a <- [2..n], b <- [a+1..n], 
                                        c <- [b+1..n], a*a + b*b == c*c ]
    

    (but this produces a lot of duplicates). I'd prefer to first fix the biggest, c value, and then find the a and b such that a < b < c, and the condition holds:

                         = [(a, b, c) | n <- [1..],
                                        c <- [2..n], a <- [2..c-1], 
                                        b <- [a+1..c-1], a*a + b*b == c*c ]
    

    but what do we need that n for, now? We don't:

    pythagoreanTriples = [(a, b, c) | c <- [2..], a <- [2..c-1], 
                                      b <- [a+1..c-1], a*a + b*b == c*c ]
    

    So that

    GHCi> take 20 pythagoreanTriples

    [(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17),(12,16,20),(7,24,25),(15,20,25),
    (10,24,26),(20,21,29),(18,24,30),(16,30,34),(21,28,35),(12,35,37),(15,36,39),(24
    ,32,40),(9,40,41),(27,36,45),(14,48,50),(30,40,50)]

    (the case a==b is impossible, because sqrt(2) is an irrational number).