Ранее я использовал альтернативные функции ([четные, нечетные]) в списках. Я не всегда был уверен, что они были наиболее эффективными. Недостаток, как я увидел, заключался в том, что они делали два или более проходов по списку источников. Для этого я выбрал другой подход, однако эффективность не очень важна для небольших наборов данных.
Это то, что я написал
lc xs ys = [[(a,b,c)|(a,b,c)<-ls,c==a+b] ++ [(a,b,c)|(a,b,c)<-ls,c==a-b]]
where ls = [(a,b,c)| a<-xs, b<-xs, c<-ys, even c]
Это было быстрее, чем ваша первоначальная функция, и быстрее, чем другой ответ. Что было более поразительно, так это то, что он использовал гораздо меньше памяти, чем любой.
Одно дело выбирать значения из длинного списка, а другое - просто устанавливать их из сгенерированных значений.
lc xs = [(a,b,c)|a<-xs,b<-xs,c<-[(a-b),(a+b)],even c]
partition (\(a,b,c) -> c == a+b) lc [1..4]