elmcraft/core-extra/1.0.0

NOTE: the latest version is 2.3.0

Basics.Extra

Additional basic functions.

Numbers

The maximum safe value for an integer, defined as 2^53 - 1. Anything larger than that and behaviour becomes mathematically unsound.

maxSafeInteger + 1 --> maxSafeInteger + 2

The minimum safe value for an integer, defined as -(2^53 - 1). Anything smaller than that, and behaviour becomes mathematically unsound.

minSafeInteger - 1 --> minSafeInteger - 2
isSafeInteger : Int -> Bool

Checks if a given integer is within the safe range, meaning it is between -(2^53 - 1) and 2^53 - 1.

isSafeInteger 5 --> True


isSafeInteger maxSafeInteger --> True


isSafeInteger (maxSafeInteger + 1) --> False

Math

safeDivide : Float -> Float -> Maybe Float

Perform floating-point division (like Elm's / operator) that will never crash the app. If the y argument in safeDivide x y is zero, we return Nothing.

safeDivide 5 2 --> Just 2.5


-- the interesting part
safeDivide 5 0 --> Nothing
safeIntegerDivide : Int -> Int -> Maybe Int

Perform integer division (like Elm's // operator) that will never crash the app. If the y argument in safeIntegerDivide x y is zero, we return Nothing.

safeIntegerDivide 5 2 --> Just 2


-- the interesting part
safeIntegerDivide 5 0 --> Nothing
safeModBy : Int -> Int -> Maybe Int

Perform modular arithmetic that will never crash the app. If the modulus argument in safeModBy modulus x is zero, we return Nothing.

safeModBy 2 4 --> Just 0


safeModBy 2 5 --> Just 1


-- the interesting part
safeModBy 0 4 --> Nothing

Use safeRemainderBy for a different treatment of negative numbers, or read Daan Leijen’s Division and Modulus for Computer Scientists for more information.

safeRemainderBy : Int -> Int -> Maybe Int

Get the remainder after division in a way that will never crash the app. If the divisor argument in safeRemainderBy divisor x is zero, we return Nothing.

safeRemainderBy 2 4 --> Just 0


safeRemainderBy 2 5 --> Just 1


-- the interesting part
safeRemainderBy 0 4 --> Nothing

Use safeModBy for a different treatment of negative numbers, or read Daan Leijen’s Division and Modulus for Computer Scientists for more information.

Angles

inDegrees : Float -> Float

Convert standard Elm angles (radians) to degrees.

inDegrees (turns 2) --> 720


inDegrees pi --> 180
inRadians : Float -> Float

Convert standard Elm angles (radians) to radians.

inRadians (degrees 90) == pi / 2


inRadians (turns 1) == 2 * pi
inTurns : Float -> Float

Convert standard Elm angles (radians) to turns. One turn is equal to 360°.

inTurns (degrees 180) == 0.5


inTurns (3 * pi) == 1.5

Higher-Order Helpers

flip : (a -> b -> c) -> b -> a -> c

Flip the order of the first two arguments to a function.

curry : (( a, b ) -> c) -> a -> b -> c

Change how arguments are passed to a function. This splits paired arguments into two separate arguments.

uncurry : (a -> b -> c) -> ( a, b ) -> c

Change how arguments are passed to a function. This combines two arguments into a single pair.

Deprecated functions

These functions are deprecated and will be removed in the next major version of this library.

swap : ( a, b ) -> ( b, a )

Swaps the elements in a pair.

swap ( 1, 2 ) --> ( 2, 1 )

@deprecated in favour of Tuple.Extra.flip.

atMost : comparable -> comparable -> comparable

Defines an upper bound for a variable.

42 |> atMost 0 --> 0


-42 |> atMost 0 --> -42

@deprecated in favour of min

atLeast : comparable -> comparable -> comparable

Defines a lower bound for a variable.

-42 |> atLeast 0 --> 0


42 |> atLeast 0 --> 42

@deprecated in favour of max

fractionalModBy : Float -> Float -> Float

Perform modular arithmetic involving floating point numbers.

The sign of the result is the same as the sign of the modulus in fractionalModBy modulus x.

fractionalModBy 2.5 5 --> 0


fractionalModBy 2 4.5 == 0.5


fractionalModBy 2 -4.5 == 1.5


fractionalModBy -2 4.5 == -1.5

@deprecated in favour of Float.Extra.modBy

orderBy : List (a -> a -> Order) -> a -> a -> Order

Create an ordering function that can be used to sort lists by multiple dimensions, by flattening multiple ordering functions into one.

This is equivalent to ORDER BY in SQL. The ordering function will order its inputs based on the order that they appear in the List (a -> a -> Order) argument.

type alias Pen =
    { model : String
    , tipWidthInMillimeters : Float
    }


pens : List Pen
pens =
    [ Pen "Pilot Hi-Tec-C Gel" 0.4
    , Pen "Morning Glory Pro Mach" 0.38
    , Pen "Pilot Hi-Tec-C Coleto" 0.5
    ]


order : Pen -> Pen -> Order
order =
    orderBy [ toOrder .tipWidthInMillimeters, toOrder .model ]


List.sortWith order pens
--> [ Pen "Morning Glory Pro Mach" 0.38
--> , Pen "Pilot Hi-Tec-C Gel" 0.4
--> , Pen "Pilot Hi-Tec-C Coleto" 0.5
--> ]

If our Pen type alias above was represented a row in a database table, our order function as defined above would be equivalent to this SQL clause:

ORDER BY tipWidthInMillimeters, model

@deprected in favor of Order.Extra.breakTies

toOrder : (a -> comparable) -> a -> a -> Order

Helper for multi-dimensional sort.

Takes a function that extracts a comparable value from a type a as a key, and returns a function a -> a -> Order.

This is primarily a helper function for the orderBy function above.

{- Simple example: wrapping a function that turns
   a custom type into an instance of `comparable`
-}


type Color
    = Red
    | Yellow
    | Green


colorToComparable : Color -> Int
colorToComparable light =
    case light of
        Red -> 0
        Yellow -> 1
        Green -> 2


colorToOrder : Color -> Color -> Order
colorToOrder =
    toOrder colorToComparable


List.sortWith
    colorToOrder
    [ Yellow, Yellow, Red, Green, Red ]
--> [ Red, Red, Yellow, Yellow, Green ]




{- More interesting example: using the property accessor
   methods on a custom type with `toOrder`; we only need
   this function when we want to combine multiple ordering functions into one.
-}


type alias Light =
    { color : Color
    , action : String
    , timeActivatedSeconds : Float
    }


lights : List Light
lights =
    [ Light Green "Go" 60
    , Light Yellow "Slow down" 5.5
    , Light Red "Stop" 60
    ]


List.sortWith
    ( orderBy
        [ toOrder .timeActivatedSeconds
        , toOrder (.color >> colorToComparable)
        ]
    )
    lights
--> [ Light Yellow "Slow down" 5.5
--> , Light Red "Stop" 60
--> , Light Green "Go" 60
--> ]

(Note that List.sortWith colorOrder above is identical to List.sortBy colorToComparable.)

@deprecated in favour of Order.Extra.byField.

toOrderDesc : (a -> comparable) -> a -> a -> Order

Same as toOrder, with flipped comparisons to enable "sort by descending".

type Color
    = Red
    | Yellow
    | Green


colorToComparable : Color -> Int
colorToComparable light =
    case light of
        Red -> 0
        Yellow -> 1
        Green -> 2


colorToOrder : Color -> Color -> Order
colorToOrder =
    toOrderDesc colorToComparable


List.sortWith
    colorToOrder
    [ Yellow, Yellow, Red, Green, Red ]
--> [ Green, Yellow, Yellow, Red, Red ]

@deprecated in favour of Order.Extra.byField >> Order.Extra.reverse