{-# LANGUAGE Safe #-} module Data.Order.Total ( -- * Total orders TotalOrder , min ,max , compare , comparing -- * DerivingVia , Total(..) -- * Re-exports , Ord.Ord() ) where import safe Control.Exception import safe Data.Order import safe qualified Data.Ord as Ord import Prelude hiding (Ord(..)) infix 4 `min`, `max`, `compare`, `comparing` -- | Find the minimum of two values. -- -- > min x y == if x <= y then x else y = True -- -- /Note/: this function will throw a /ArithException/ on floats and rationals -- if one of the arguments is finite and the other is /NaN/. -- min :: TotalOrder a => a -> a -> a min x y = case compare x y of GT -> y _ -> x -- | Find the minimum of two values. -- -- > max x y == if x >= y then x else y = True -- -- /Note/: this function will throw a /ArithException/ on floats and rationals -- if one of the arguments is finite and the other is /NaN/. -- max :: TotalOrder a => a -> a -> a max x y = case compare x y of LT -> y _ -> x -- | Compare two values in a total order. -- -- > x < y = compare x y == LT -- > x > y = compare x y == GT -- > x == y = compare x y == EQ -- -- >>> compare (1/0 :: Double) 0 -- GT -- >>> compare (-1/0 :: Double) 0 -- LT -- >>> compare (1/0 :: Double) (0/0) -- GT -- >>> compare (-1/0 :: Double) (0/0) -- LT -- -- /Note/: this function will throw a /ArithException/ on floats and rationals -- if one of the arguments is finite and the other is /NaN/: -- -- >>> compare (0/0 :: Double) 0 -- *** Exception: divide by zero -- compare :: TotalOrder a => a -> a -> Ordering compare x y = case pcompare x y of Just o -> o Nothing -> throw DivideByZero -- | -- > comparing p x y = compare (p x) (p y) -- -- Useful combinator for use in conjunction with the @xxxBy@ family -- of functions from "Data.List", for example: -- -- > ... sortBy (comparing fst) ... comparing :: TotalOrder a => (b -> a) -> b -> b -> Ordering comparing p x y = compare (p x) (p y)