{-# OPTIONS_GHC -XFlexibleContexts #-}

-- | A number of handy functions, type aliases, and reexports all having to do with ordering operations.
module Data.RangeMin.Internal.HandyOrdering(Comparator, orderPairBy, 
orderPair, minBy, maxBy, maximumBy, minimumBy, comparing) where

import Data.List(maximumBy, minimumBy)
import Data.RangeMin.Internal.Combinators(on)

-- | A handy shorthand for a frequently occurring function.
type Comparator e = e -> e -> Ordering

-- | @comparing f (x y)@ is equivalent to @compare (f x) (f y)@.
comparing :: Ord b => (a -> b) -> Comparator a
comparing f = compare `on` f

-- | @orderPairBy cmp (x, y)@ is equivalent to @if cmp x y == GT then (y, x) else (x, y)@.
orderPairBy :: Comparator e -> (e, e) -> (e, e)
orderPairBy cmp (x,y) = if cmp x y == GT then (y,x) else (x,y)

-- | @orderPairBy cmp (x, y)@ is equivalent to @if x <= y then (y, x) else (x, y)@.
orderPair :: Ord e => (e, e) -> (e, e)
orderPair (x,y) = if x <= y then (x, y) else (y, x)

-- | @minBy cmp x y@ returns the smaller of @x@ and @y@ by the specified comparator.
minBy :: Comparator e -> e -> e -> e
minBy cmp x y = if cmp x y == GT then y else x

-- | @maxBy cmp x y@ returns the larger of @x@ and @y@ by the specified comparator.
maxBy :: Comparator e -> e -> e -> e
maxBy = minBy . flip