Current section
Files
Jump to
Current section
Files
lib/Data/Ord.hm
-----------------------------------------------------------------------------
-- |
-- 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