Skip to content

Some extra functions, fixes #20 #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions docs/Prelude.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
78 changes: 73 additions & 5 deletions src/Prelude.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
-- |
Expand Down