diff --git a/docs/Prelude.md b/docs/Prelude.md index c5ffa2b1..110a4b82 100644 --- a/docs/Prelude.md +++ b/docs/Prelude.md @@ -551,6 +551,14 @@ Instances must satisfy the following laws: `(*)` is an alias for `mul`. +#### `succ` + +``` purescript +succ :: forall a. (Semiring a) => a -> a +``` + +Adds `one` to a value. + #### `Ring` ``` purescript @@ -589,6 +597,23 @@ negate :: forall a. (Ring a) => a -> a `negate x` can be used as a shorthand for `zero - x`. +#### `pred` + +``` purescript +pred :: forall a. (Ring a) => a -> a +``` + +Subtracts `one` from a value. + +#### `abs` + +``` purescript +abs :: forall a. (Ord a, Ring a) => a -> a +``` + +The absolute value of a value. Defined as +`if x <= zero then negate x else x`. + #### `ModuloSemiring` ``` purescript @@ -620,6 +645,15 @@ laws: `(/)` is an alias for `div`. +#### `sigNum` + +``` purescript +sigNum :: forall a. (Ord a, Ring a, ModuloSemiring a) => a -> a +``` + +The 'sign' of a value. Defined as +`if x == zero then zero else x / abs x`. + #### `DivisionRing` ``` purescript @@ -678,6 +712,7 @@ instance eqString :: Eq String instance eqUnit :: Eq Unit instance eqArray :: (Eq a) => Eq (Array a) instance eqOrdering :: Eq Ordering +instance eqDesc :: (Eq a) => Eq (Desc a) ``` The `Eq` type class represents types which support decidable equality. @@ -702,6 +737,16 @@ The `Eq` type class represents types which support decidable equality. (/=) :: forall a. (Eq a) => a -> a -> Boolean ``` +#### `equaling` + +``` purescript +equaling :: forall a b. (Eq b) => (a -> b) -> a -> a -> Boolean +``` + +Given a function `a -> b`, create a new binary function which takes two +`a` values and returns true if and only if the results of the given +function are equal. + #### `Ordering` ``` purescript @@ -744,6 +789,7 @@ instance ordChar :: Ord Char instance ordUnit :: Ord Unit instance ordArray :: (Ord a) => Ord (Array a) instance ordOrdering :: Ord Ordering +instance ordDesc :: (Ord a) => Ord (Desc a) ``` The `Ord` type class represents types which support comparisons. @@ -786,6 +832,80 @@ Test whether one value is _non-strictly less than_ another. Test whether one value is _non-strictly greater than_ another. +#### `min` + +``` purescript +min :: forall a. (Ord a) => a -> a -> a +``` + +Choose the smaller of two values. If they compare `EQ`, the first is +chosen. For example: `min 0 1 == 0`. + +#### `max` + +``` purescript +max :: forall a. (Ord a) => a -> a -> a +``` + +Choose the larger of two values. If they compare `EQ`, the first is +chosen. For example: `max 0 1 == 1`. + +#### `clamp` + +``` purescript +clamp :: forall a. (Ord a) => a -> a -> a -> a +``` + +Ensure that a value is between a lower and upper bound. For example: +`let f = clamp 0 10 in map f [-5, 5, 15] == [0, 5, 10]` + +#### `between` + +``` purescript +between :: forall a. (Ord a) => a -> a -> a -> Boolean +``` + +Test if a value is between two other values. For example: +`let f = between 0 10 in map f [-5, 5, 15] = [false, true, false]` + +#### `ascending` + +``` purescript +ascending :: forall a b. (Ord b) => (a -> b) -> a -> a -> Ordering +``` + +Compare two values based on the results of applying the given function +to both of them. Useful with functions like `Data.Array.sortBy`. For +example, `sortBy (ascending _.x)` will sort an array of records by their +`x` property, in ascending order. + +#### `descending` + +``` purescript +descending :: forall a b. (Ord b) => (a -> b) -> a -> a -> Ordering +``` + +Compare two values based on the results of applying the given function +to both of them, but flipped. Useful with functions like +`Data.Array.sortBy`. For example, `sortBy (descending _.x)` will sort an +array of records by their `x` property, in descending order. + +#### `Desc` + +``` purescript +newtype Desc a + = Desc a +``` + +##### Instances +``` purescript +instance eqDesc :: (Eq a) => Eq (Desc a) +instance ordDesc :: (Ord a) => Ord (Desc a) +``` + +The `Desc` newtype reverses the order of a type's `Ord` instance. For +example: `Desc 5 < Desc 6 == true`. + #### `Bounded` ``` purescript diff --git a/src/Prelude.purs b/src/Prelude.purs index e2f03cda..b234144c 100644 --- a/src/Prelude.purs +++ b/src/Prelude.purs @@ -13,13 +13,13 @@ module Prelude , Bind, bind, (>>=) , Monad, return, liftM1, ap , Semigroup, append, (<>), (++) - , Semiring, add, zero, mul, one, (+), (*) - , ModuloSemiring, div, mod, (/) - , Ring, sub, negate, (-) + , Semiring, add, zero, mul, one, (+), (*), succ + , ModuloSemiring, div, mod, (/), sigNum + , Ring, sub, negate, (-), pred, abs , Num , DivisionRing - , Eq, eq, (==), (/=) - , Ordering(..), Ord, compare, (<), (>), (<=), (>=) + , Eq, eq, (==), (/=), equaling + , Ordering(..), Ord, compare, (<), (>), (<=), (>=), min, max, clamp, between, ascending, descending, Desc(..) , Bounded, top, bottom , Lattice, sup, inf, (||), (&&) , BoundedLattice @@ -475,6 +475,10 @@ foreign import intMul :: Int -> Int -> Int foreign import numAdd :: Number -> Number -> Number foreign import numMul :: Number -> Number -> Number +-- | Adds `one` to a value. +succ :: forall a. (Semiring a) => a -> a +succ x = x + one + infixl 6 - -- | The `Ring` class is for types that support addition, multiplication, @@ -507,6 +511,15 @@ negate a = zero - a foreign import intSub :: Int -> Int -> Int foreign import numSub :: Number -> Number -> Number +-- | Subtracts `one` from a value. +pred :: forall a. (Ring a) => a -> a +pred x = x - one + +-- | The absolute value of a value. Defined as +-- | `if x <= zero then negate x else x`. +abs :: forall a. (Ord a, Ring a) => a -> a +abs x = if x <= zero then negate x else x + infixl 7 / -- | The `ModuloSemiring` class is for types that support addition, @@ -540,6 +553,11 @@ foreign import intDiv :: Int -> Int -> Int foreign import numDiv :: Number -> Number -> Number foreign import intMod :: Int -> Int -> Int +-- | The 'sign' of a value. Defined as +-- | `if x == zero then zero else x / abs x`. +sigNum :: forall a. (Ord a, Ring a, ModuloSemiring a) => a -> a +sigNum x = if x == zero then zero else x / abs x + -- | A `Ring` where every nonzero element has a multiplicative inverse. -- | -- | Instances must satisfy the following law in addition to the `Ring` and @@ -612,6 +630,12 @@ instance eqOrdering :: Eq Ordering where eq EQ EQ = true eq _ _ = false +-- | Given a function `a -> b`, create a new binary function which takes two +-- | `a` values and returns true if and only if the results of the given +-- | function are equal. +equaling :: forall a b. (Eq b) => (a -> b) -> a -> a -> Boolean +equaling f x y = f x == f y + foreign import refEq :: forall a. a -> a -> Boolean foreign import refIneq :: forall a. a -> a -> Boolean foreign import eqArrayImpl :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean @@ -703,6 +727,50 @@ unsafeCompare = unsafeCompareImpl LT EQ GT foreign import unsafeCompareImpl :: forall a. Ordering -> Ordering -> Ordering -> a -> a -> Ordering +-- | Choose the smaller of two values. If they compare `EQ`, the first is +-- | chosen. For example: `min 0 1 == 0`. +min :: forall a. (Ord a) => a -> a -> a +min x y = if x <= y then x else y + +-- | Choose the larger of two values. If they compare `EQ`, the first is +-- | chosen. For example: `max 0 1 == 1`. +max :: forall a. (Ord a) => a -> a -> a +max x y = if x >= y then x else y + +-- | Ensure that a value is between a lower and upper bound. For example: +-- | `let f = clamp 0 10 in map f [-5, 5, 15] == [0, 5, 10]` +clamp :: forall a. (Ord a) => a -> a -> a -> a +clamp low high x = max low (min high x) + +-- | Test if a value is between two other values. For example: +-- | `let f = between 0 10 in map f [-5, 5, 15] = [false, true, false]` +between :: forall a. (Ord a) => a -> a -> a -> Boolean +between low high x = low <= x && x <= high + +-- | Compare two values based on the results of applying the given function +-- | to both of them. Useful with functions like `Data.Array.sortBy`. For +-- | example, `sortBy (ascending _.x)` will sort an array of records by their +-- | `x` property, in ascending order. +ascending :: forall a b. (Ord b) => (a -> b) -> a -> a -> Ordering +ascending f x y = compare (f x) (f y) + +-- | Compare two values based on the results of applying the given function +-- | to both of them, but flipped. Useful with functions like +-- | `Data.Array.sortBy`. For example, `sortBy (descending _.x)` will sort an +-- | array of records by their `x` property, in descending order. +descending :: forall a b. (Ord b) => (a -> b) -> a -> a -> Ordering +descending f x y = compare (f y) (f x) + +-- | The `Desc` newtype reverses the order of a type's `Ord` instance. For +-- | example: `Desc 5 < Desc 6 == true`. +newtype Desc a = Desc a + +instance eqDesc :: (Eq a) => Eq (Desc a) where + eq (Desc x) (Desc y) = x == y + +instance ordDesc :: (Ord a) => Ord (Desc a) where + compare (Desc x) (Desc y) = compare y x + -- | The `Bounded` type class represents types that are finite partially -- | ordered sets. -- |