module Relation.Binary.Comparison (module Relation.Binary.Comparison, Ordering (..)) where import Prelude (Char, Integer) import qualified Prelude import Algebra import Control.Applicative import Control.Monad import Data.Bits import Data.Bool import Data.Either import Data.Function (flip, on) import Data.Int import Data.Maybe import Data.Monoid (Sum (..)) import Data.Ord (Down (..), Ordering (..)) import Data.Ratio import Data.Word import Numeric.Natural infix 4 ≤, ≥, <, >, ≡, ≢ class Preord a where {-# MINIMAL (≥) | (≤) #-} (≤), (≥), (<), (>) :: a -> a -> Bool (≤) = flip (≥) (≥) = flip (≤) a < b = a ≤ b && not (a ≥ b) (>) = flip (<) class PartialEq a where {-# MINIMAL (≡) | (≢) #-} (≡), (≢) :: a -> a -> Bool a ≡ b = not (a ≢ b) a ≢ b = not (a ≡ b) class (Preord a, PartialEq a) => Eq a class (Preord a, PartialEq a) => PartialOrd a where tryCompare :: a -> a -> Maybe Ordering tryCompare a b = case (a ≤ b, b ≤ a) of (False, False) -> Nothing (False, True) -> Just GT (True, False) -> Just LT (True, True) -> Just EQ class (PartialOrd a, Eq a) => Ord a where compare :: a -> a -> Ordering compare a b = fromJust (tryCompare a b) instance Preord a => Preord (Down a) where Down a ≤ Down b = a ≥ b Down a ≥ Down b = a ≤ b Down a < Down b = a > b Down a > Down b = a < b deriving via (a :: *) instance PartialEq a => PartialEq (Down a) instance PartialOrd a => PartialOrd (Down a) where Down a `tryCompare` Down b = tryCompare b a deriving via (a :: *) instance Eq a => Eq (Down a) instance Ord a => Ord (Down a) instance Preord () where () ≤ () = True instance PartialEq () where () ≡ () = True instance PartialOrd () where tryCompare () () = Just EQ instance Eq () instance Ord () instance Preord Bool where (≤) = (Prelude.<=) instance PartialEq Bool where (≡) = (Prelude.==) instance PartialOrd Bool where tryCompare a b = Just (Prelude.compare a b) instance Eq Bool instance Ord Bool instance Preord Ordering where (≤) = (Prelude.<=) instance PartialEq Ordering where (≡) = (Prelude.==) instance PartialOrd Ordering where tryCompare a b = Just (Prelude.compare a b) instance Eq Ordering instance Ord Ordering instance Preord Natural where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Natural where (≡) = (Prelude.==) instance PartialOrd Natural where tryCompare a b = Just (Prelude.compare a b) instance Eq Natural instance Ord Natural instance Preord Integer where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Integer where (≡) = (Prelude.==) instance PartialOrd Integer where tryCompare a b = Just (Prelude.compare a b) instance Eq Integer instance Ord Integer instance Preord Int where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Int where (≡) = (Prelude.==) instance PartialOrd Int where tryCompare a b = Just (Prelude.compare a b) instance Eq Int instance Ord Int instance Preord Int8 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Int8 where (≡) = (Prelude.==) instance PartialOrd Int8 where tryCompare a b = Just (Prelude.compare a b) instance Eq Int8 instance Ord Int8 instance Preord Int16 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Int16 where (≡) = (Prelude.==) instance PartialOrd Int16 where tryCompare a b = Just (Prelude.compare a b) instance Eq Int16 instance Ord Int16 instance Preord Int32 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Int32 where (≡) = (Prelude.==) instance PartialOrd Int32 where tryCompare a b = Just (Prelude.compare a b) instance Eq Int32 instance Ord Int32 instance Preord Int64 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Int64 where (≡) = (Prelude.==) instance PartialOrd Int64 where tryCompare a b = Just (Prelude.compare a b) instance Eq Int64 instance Ord Int64 instance Preord Word where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Word where (≡) = (Prelude.==) instance PartialOrd Word where tryCompare a b = Just (Prelude.compare a b) instance Eq Word instance Ord Word instance Preord Word8 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Word8 where (≡) = (Prelude.==) instance PartialOrd Word8 where tryCompare a b = Just (Prelude.compare a b) instance Eq Word8 instance Ord Word8 instance Preord Word16 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Word16 where (≡) = (Prelude.==) instance PartialOrd Word16 where tryCompare a b = Just (Prelude.compare a b) instance Eq Word16 instance Ord Word16 instance Preord Word32 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Word32 where (≡) = (Prelude.==) instance PartialOrd Word32 where tryCompare a b = Just (Prelude.compare a b) instance Eq Word32 instance Ord Word32 instance Preord Word64 where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Word64 where (≡) = (Prelude.==) instance PartialOrd Word64 where tryCompare a b = Just (Prelude.compare a b) instance Eq Word64 instance Ord Word64 instance Preord Char where (≤) = (Prelude.<=) (<) = (Prelude.<) instance PartialEq Char where (≡) = (Prelude.==) instance PartialOrd Char where tryCompare a b = Just (Prelude.compare a b) instance Eq Char instance Ord Char instance (PartialEq a, PartialEq b) => PartialEq (a, b) where (aₗ, bₗ) ≡ (aᵣ, bᵣ) = aₗ ≡ aᵣ && bₗ ≡ bᵣ instance (Preord a, Preord b) => Preord (a, b) where (aₗ, bₗ) ≤ (aᵣ, bᵣ) = aₗ ≤ aᵣ && bₗ ≤ bᵣ instance (PartialOrd a, PartialOrd b) => PartialOrd (a, b) where tryCompare (aₗ, bₗ) (aᵣ, bᵣ) = liftA2 (,) (tryCompare aₗ aᵣ) (tryCompare bₗ bᵣ) >>= \ case (EQ, y) -> Just y (x, EQ) -> Just x (LT, LT) -> Just LT (GT, GT) -> Just GT _ -> Nothing instance (PartialOrd a, PartialOrd b) => Preord (Lexical (a, b)) where a ≤ b = Just GT ≢ tryCompare a b a < b = Just LT ≡ tryCompare a b instance (PartialOrd a, PartialOrd b) => PartialOrd (Lexical (a, b)) where Lexical (aₗ, bₗ) `tryCompare` Lexical (aᵣ, bᵣ) = tryCompare aₗ aᵣ <> tryCompare bₗ bᵣ instance (PartialOrd a, PartialOrd b, Eq a, Eq b) => Eq (Lexical (a, b)) instance (Ord a, Ord b) => Ord (Lexical (a, b)) instance (PartialEq a, PartialEq b, PartialEq c) => PartialEq (a, b, c) where (aₗ, bₗ, cₗ) ≡ (aᵣ, bᵣ, cᵣ) = aₗ ≡ aᵣ && bₗ ≡ bᵣ && cₗ ≡ cᵣ instance (Preord a, Preord b, Preord c) => Preord (a, b, c) where (aₗ, bₗ, cₗ) ≤ (aᵣ, bᵣ, cᵣ) = aₗ ≤ aᵣ && bₗ ≤ bᵣ && cₗ ≤ cᵣ instance (PartialOrd a, PartialOrd b, PartialOrd c) => PartialOrd (a, b, c) where tryCompare (aₗ, bₗ, cₗ) (aᵣ, bᵣ, cᵣ) = tryCompare (aₗ, (bₗ, cₗ)) (aᵣ, (bᵣ, cᵣ)) instance (PartialOrd a, PartialOrd b, PartialOrd c) => Preord (Lexical (a, b, c)) where a ≤ b = Just GT ≢ tryCompare a b a < b = Just LT ≡ tryCompare a b instance (PartialOrd a, PartialOrd b, PartialOrd c) => PartialOrd (Lexical (a, b, c)) where Lexical (aₗ, bₗ, cₗ) `tryCompare` Lexical (aᵣ, bᵣ, cᵣ) = tryCompare aₗ aᵣ <> tryCompare bₗ bᵣ <> tryCompare cₗ cᵣ instance (PartialOrd a, PartialOrd b, PartialOrd c, Eq a, Eq b, Eq c) => Eq (Lexical (a, b, c)) instance (Ord a, Ord b, Ord c) => Ord (Lexical (a, b, c)) instance (Preord a, Preord b) => Preord (Either a b) where Left x ≤ Left y = x ≤ y Right x ≤ Right y = x ≤ y _ ≤ _ = False instance (PartialEq a, PartialEq b) => PartialEq (Either a b) where Left x ≡ Left y = x ≡ y Right x ≡ Right y = x ≡ y _ ≡ _ = False instance (PartialOrd a, PartialOrd b) => PartialOrd (Either a b) where Left x `tryCompare` Left y = x `tryCompare` y Right x `tryCompare` Right y = x `tryCompare` y _ `tryCompare` _ = Nothing instance (Preord a, Preord b) => Preord (Lexical (Either a b)) where Lexical (Left _) ≤ Lexical (Right _) = True Lexical x ≤ Lexical y = x ≤ y instance (PartialOrd a, PartialOrd b) => PartialOrd (Lexical (Either a b)) where Lexical (Left _) `tryCompare` Lexical (Right _) = Just LT Lexical (Right _) `tryCompare` Lexical (Left _) = Just GT Lexical x `tryCompare` Lexical y = tryCompare x y instance (Eq a, Eq b) => Eq (Lexical (Either a b)) instance (Ord a, Ord b) => Ord (Lexical (Either a b)) instance (Preord a) => Preord (Lexical (Maybe a)) where Lexical Nothing ≤ Lexical (Just _) = True Lexical x ≤ Lexical y = x ≤ y instance (PartialOrd a) => PartialOrd (Lexical (Maybe a)) where Lexical Nothing `tryCompare` Lexical (Just _) = Just LT Lexical (Just _) `tryCompare` Lexical Nothing = Just GT Lexical x `tryCompare` Lexical y = tryCompare x y instance (Eq a) => Eq (Lexical (Maybe a)) instance (Ord a) => Ord (Lexical (Maybe a)) newtype Lexical a = Lexical { unLexical :: a } deriving (PartialEq, Semigroup, Monoid, Group) via a instance PartialEq a => PartialEq (Maybe a) where (≡) = (≡) `on` maybe (Left ()) Right instance Preord a => Preord (Maybe a) where (≤) = (≤) `on` maybe (Left ()) Right instance PartialOrd a => PartialOrd (Maybe a) where tryCompare = tryCompare `on` maybe (Left ()) Right instance Eq a => Eq (Maybe a) class (Monoid a, Abelian a, PartialOrd a) => Monus a where monus :: a -> a -> a deriving via Natural instance Preord (Sum Natural) deriving via Natural instance PartialEq (Sum Natural) deriving via Natural instance PartialOrd (Sum Natural) deriving via Natural instance Eq (Sum Natural) deriving via Natural instance Ord (Sum Natural) instance Monus (Sum Natural) where 0 `monus` _ = 0 a `monus` 0 = a a `monus` b = (a Prelude.- 1) `monus` (b Prelude.- 1) (∸) :: Monus (Sum a) => a -> a -> a a ∸ b = getSum (Sum a `monus` Sum b) max, min :: Ord a => a -> a -> a max a b | a > b = a | otherwise = b min a b | a < b = a | otherwise = b newtype Max a = Max { unMax :: a } deriving (Prelude.Eq, Bits, FiniteBits, Prelude.Read, Prelude.Show) via a newtype Min a = Min { unMin :: a } deriving (Prelude.Eq, Bits, FiniteBits, Prelude.Read, Prelude.Show) via a instance {-# OVERLAPPABLE #-} Ord a => Semigroup (Max a) where Max a <> Max b = Max (max a b) instance {-# OVERLAPPABLE #-} Ord a => Semigroup (Min a) where Min a <> Min b = Min (min a b) instance PartialEq a => PartialEq (Ratio a) where (≡) = (≡) `on` liftA2 (,) numerator denominator instance PartialEq a => PartialEq [a] where [] ≡ [] = True x:xs ≡ y:ys = (x, xs) ≡ (y, ys) _ ≡ _ = False