lue-bird/elm-bounded-nat - version: 35.0.0

for more information visit the package's GitHub page

Package contains the following modules:

bounded-nat

Natural number ≥ 0 that has extra information about its range at compile-time

example: toHexChar

toHexChar : Int -> Char

with bounded-nat:

toHexChar : N (In min_ (Up maxTo15_ To N15)) -> Char

The argument type says: Give me an integer ≥ 0 N In range - ≥ 0any minimum allowed → min_ type variable that's only used once - ≤ 15 → if we increase some number (maxTo15_ type variable that's only used once) by the argument's maximum, we get N15

Users can prove this by explicitly

example: toDigit

toDigit : Char -> Maybe Int

You might be able to do anything with this Int value, but you lost useful information:

toDigit :
    Char -> Maybe (N (In (Up0 minX_) (Up9 maxX_)))

The type of an N value will reflect how much you and the compiler know

example: factorial

intFactorial : Int -> Int
intFactorial x =
    case x of
        0 ->
            1

        non0 ->
            non0 * intFactorial (non0 - 1)

This forms an infinite loop if we call intFactorial -1...

Let's disallow negative numbers here (& more)!

import N exposing (N, In, Min, Up1, n1, n4)

         -- for every `n ≥ 0`, `n! ≥ 1`
factorial : N (In min_ max_) -> N (Min (Up1 x_))
factorial =
    factorialBody

factorialBody : N (In min_ max_) -> N (Min (Up1 x_))
factorialBody x =
    case x |> N.isAtLeast n1 of
        Err _ ->
            n1 |> N.maxToInfinity
        Ok xMin1 ->
            -- xMin1 : N (Min ..1..), so xMin1 - 1 ≥ 0
            factorial (xMin1 |> N.subtractMin n1)
                |> N.multiplyBy xMin1

factorial n4 |> N.toInt --> 24

Separate factorial & factorialBody are needed because there's no support for polymorphic recursion 😢

We can do even better! !19 is already > the maximum safe Int 2^53 - 1

safeFactorial : N (In min_ (Up maxTo18_ To N18)) -> N (Min (Up1 x_))
safeFactorial =
    factorial

No extra work

tips

ready? go!