First of all, this style is actually quite idiomatic. Since you do two things with two different meanings, there is some irreducible complexity; Actual pattern matching does little. In addition, I personally believe that explicit style is very readable most of the time.
However, there is an alternative. Control.Arrow has tons of functions for working with tuples. Since the arrow -> function -> also an Arrow , they all work for normal functions.
So, you can rewrite your second example using (***) to combine the two functions for working on tuples. This statement has the following type:
(***) :: abc -> ab' c' -> a (b, b') (c, c')
If we replace a with -> , we get:
(***) :: (b -> c) -> (b' -> c') -> ((b, b') -> (c, c'))
So you can combine (+ x) and (- x) into one function with (+ x) *** (- x) . This will be equivalent to:
\ (a, b) -> (a + x, b - x)
Then you can use it in your recursion. Unfortunately, the operator is stupid and does not work in partitions, so you have to write it using lambda:
(+ x) *** (\ a -> a - x) $ go xs
You obviously can imagine using any other operator, all of which are not so stupid :).
Honestly, I think this version is less readable than the original. However, in other cases, the *** version may be more readable, so itβs useful to know about it. In particular, if you passed (+ x) *** (- x) to a higher order function instead of applying it immediately, I think the *** version will be better than the explicit lambda.