Software! Math! Data! The blog of R. Sean Bowman
The blog of R. Sean Bowman

March 27 2016

A few days ago I was motivated to write a program in Haskell to test whether three numbers form a Pythagorean triple. There is an obvious solution, of course, but it’s always nice to shove monads in to problems that don’t need them. In this case, though, I found that the resulting solution did more than I had originally planned: if you pass the `pTriples` function a list of numbers, it will return a list of each Pythagorean triple that can be made from numbers in the list (without replacement). Cool!

The code is based on a very nice puzzle solution.

``````import Control.Monad

select [] = []
select (x:xs) = (x, xs) : [(y, x:ys) | (y,ys) <- select xs]

-- pTriples takes a list of integers and returns the list of
-- Pythagorean triples that can be made from them, eg.
-- pTriples [2, 3] is []
-- pTriples [3, 4, 5] is [(3, 4, 5)]
-- pTriples [3, 4, 9, 11] is []
-- pTriples [3, 4, 9, 5] is [(3, 4, 5)]
pTriples :: [Integer] -> [(Integer, Integer, Integer)]
pTriples = evalStateT \$ do
a <- StateT select
b <- StateT select
c <- StateT select
guard \$ a <= b
guard \$ a*a + b*b == c*c
return (a, b, c)

isTriple = not . null . pTriples
``````

Approx. 224 words, plus code