Find two numbers in a sorted array whose sum is closest to a given number Given a sorted array and a number x, find a pair in array whose sum is closest to x.


Here's my solution:

import Data.List (minimumBy)
import Data.Ord (comparing)

closestPairSum :: (Num a, Ord a) =&gt; [a] -&gt; a -&gt; (a, a)
closestPairSum xs n = snd $ minimumBy (comparing fst) pairs
  where 
    pairs = sums xs (reverse xs)
    sums xxs@(x:xs) yys@(y:ys) = let sum = x + y in
      if n &lt; sum
      then (sum - n, (x, y)) : sums xxs ys
      else (n - sum, (x, y)) : sums xs yys
    sums _ _ = []


I'm mostly self-taught, so I would love to know in which ways my code is not according to common practice. More specifically:


How can I more clearly align my let-in and if-then-else expressions?
I use an intermediate list of (a, (a, a)) tuples, which I'm not thrilled about. Is there a more elegant way to do this, without sacrificing performance?
I'm on the fence about sum xs (reverse xs) vs sum xs $ reverse xs. Is this just considered nitpicking, or do people have a strong opinion about this?
Would it make more sense to swap the parameters of this function? I have the feeling that a would usually precede [a] with pointfree style in mind, but I'm not sure about this one.
Anything else that I might not have thought of :)
The "intermediate array" takes no extra space due to lazy evaluation. minimumBy . comparing is minimumOn. Yes, swapping the parameters makes sense. Inline then and else once more. I wouldn't worry so much about constant factors - have you compiled it with -O2 and tested (eg with criterion)?

import Data.List (minimumOn)

closestPairSum :: (Num a, Ord a) =&gt; a -&gt; [a] -&gt; (a, a)
closestPairSum n xs = minimumOn (abs . (n-) . uncurry (+)) pairs where
  pairs = sums xs (reverse xs)
  sums xxs@(x:xs) yys@(y:ys) = (x, y) : if n &lt; x + y
    then sums xxs ys
    else sums xs yys
  sums _ _ = []