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
import Control.Monad.Trans.State

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