----------------------------------------------------------------------------- -- | -- Module : Data.Ord -- Copyright : (c) 2020-2021 EMQ Technologies Co., Ltd. -- License : BSD-style (see the LICENSE file) -- -- Maintainer : Feng Lee, feng@emqx.io -- Yang M, yangm@emqx.io -- Stability : experimental -- Portability : portable -- -- The Ord typeclass. -- ----------------------------------------------------------------------------- module Data.Ord ( class Ord, compare , lessThan, (<) , lessThanOrEq, (<=) , greaterThan, (>) , greaterThanOrEq, (>=) , comparing , min, max , between , module Data.Ordering ) where import Data.Eq (class Eq) import Data.Ordering (Ordering(..)) import Data.Unit (Unit) import Data.Maybe (Maybe(..)) -- import Data.Void (Void) class Eq a => Ord a where compare :: a -> a -> Ordering instance Ord Atom where compare = cmpAtomImpl LT EQ GT instance Ord Boolean where compare = cmpBoolImpl LT EQ GT instance Ord Binary where compare = cmpBinImpl LT EQ GT instance Ord Char where compare = cmpCharImpl LT EQ GT instance Ord Integer where compare = cmpIntImpl LT EQ GT instance Ord Float where compare = cmpFloatImpl LT EQ GT instance Ord Unit where compare _ _ = EQ instance (Ord a, Ord b) => Ord (a, b) where compare (x, y) (p, q) = let result = compare x p in case result of EQ -> compare y q _ -> result instance Ord a => Ord [a] where compare [] [] = EQ compare [] _ = LT compare _ [] = GT compare [x | xs] [y | ys] = let result = compare x y in case result of EQ -> compare xs ys _ -> result instance Ord a => Ord (Maybe a) where compare Nothing Nothing = EQ compare _ Nothing = GT compare Nothing _ = LT compare (Just x) (Just y) = compare x y {- instance Ord Void where compare _ _ = EQ -} foreign import cmpAtomImpl :: Ordering -> Ordering -> Ordering -> Atom -> Atom -> Ordering foreign import cmpBoolImpl :: Ordering -> Ordering -> Ordering -> Boolean -> Boolean -> Ordering foreign import cmpBinImpl :: Ordering -> Ordering -> Ordering -> Binary -> Binary -> Ordering foreign import cmpCharImpl :: Ordering -> Ordering -> Ordering -> Char -> Char -> Ordering foreign import cmpIntImpl :: Ordering -> Ordering -> Ordering -> Integer -> Integer -> Ordering foreign import cmpFloatImpl :: Ordering -> Ordering -> Ordering -> Float -> Float -> Ordering foreign import cmpStringImpl :: Ordering -> Ordering -> Ordering -> String -> String -> Ordering -- | Test whether one value is _strictly less than_ another. lessThan :: forall a. Ord a => a -> a -> Boolean lessThan a1 a2 = case a1 `compare` a2 of LT -> true _ -> false -- | Test whether one value is _strictly greater than_ another. greaterThan :: forall a. Ord a => a -> a -> Boolean greaterThan a1 a2 = case a1 `compare` a2 of GT -> true _ -> false -- | Test whether one value is _non-strictly less than_ another. lessThanOrEq :: forall a. Ord a => a -> a -> Boolean lessThanOrEq a1 a2 = case a1 `compare` a2 of GT -> false _ -> true -- | Test whether one value is _non-strictly greater than_ another. greaterThanOrEq :: forall a. Ord a => a -> a -> Boolean greaterThanOrEq a1 a2 = case a1 `compare` a2 of LT -> false _ -> true infixl 4 lessThan as < infixl 4 lessThanOrEq as <= infixl 4 greaterThan as > infixl 4 greaterThanOrEq as >= -- | Compares two values by mapping them to a type with an `Ord` instance. comparing :: forall a b. Ord b => (a -> b) -> (a -> a -> Ordering) comparing f x y = compare (f x) (f y) -- | Take the minimum of two values. If they are considered equal, the first -- | argument is chosen. min :: forall a. Ord a => a -> a -> a min x y = case compare x y of LT -> x EQ -> x GT -> y -- | Take the maximum of two values. If they are considered equal, the first -- | argument is chosen. max :: forall a. Ord a => a -> a -> a max x y = case compare x y of LT -> y EQ -> x GT -> x -- | Clamp a value between a minimum and a maximum. For example: -- | -- | ``` purescript -- | let f = clamp 0 10 -- | f (-5) == 0 -- | f 5 == 5 -- | f 15 == 10 -- | ``` clamp :: forall a. Ord a => a -> a -> a -> a clamp low hi x = min hi (max low x) -- | Test whether a value is between a minimum and a maximum (inclusive). -- | For example: -- | -- | ``` purescript -- | let f = between 0 10 -- | f 0 == true -- | f (-5) == false -- | f 5 == true -- | f 10 == true -- | f 15 == false -- | ``` between :: forall a. Ord a => a -> a -> a -> Boolean between low hi x | x < low = false | x > hi = false | true = true