indique/elm-nat-in-range/1.0.2

NOTE: the latest version is 2.0.0

MinNat

A Nat which is at least some minimum.

type alias MinNat min =
MinNat min

NatFrom min meaning a natural number which is at least min.

   ↓ minimum
⨯ [✓ ✓ ✓ ✓ ✓ ✓ ✓...

Any natural number

MinNat Nat0

A number, bigger than 4

MinNat Nat5

add information

NNat (N max Is (Difference a To maxPlusA))
-> { min : NNat (N min Is (Difference range To max)) }
-> MinNat min
-> InNat min maxPlusA

Cap the MinNat to at most a upper limit.

abs : Int -> MinNat Nat0

The absolute value of an Int, which is at least Nat0.

MinNat.abs 16 --> MinNat 16


MinNat.abs -4 --> MinNat 4

Really only use this if you want the absolute value.

badLength list =
    List.length >> MinNat.abs


goodLength =
    List.foldl
        (\_ -> MinNat.addN nat1 >> MinNat.lowerMin nat0)
        (MinNat.n nat0)

If something like this isn't possible, use [MinNat.intAtLeast][MinNat#intAtLeast] nat0!

intAtLeast : NNat (N n Is difference) -> Int -> MinNat n

A MinNat from an Int; if the Int < minimum, minimum is returned.

9 |> MinNat.intAtLeast nat3 --> MinNat 9


0 |> MinNat.intAtLeast nat3 --> MinNat 3

You can also use this if you know an Int must be at least minimum.

But avoid it if you can do better, like

goodLength =
    List.foldl
        (\_ -> MinNat.addN nat1 >> MinNat.lowerMin nat0)
        (MinNat.n nat0)

If you want to handle the case < minimum yourself, use [MinNat.isIntAtLeast][MinNat#isIntAtLeast].

compare

isIntAtLeast : NNat (N min Is difference) -> Int -> Maybe (MinNat n)

If the Int >= a minimum, Just the MinNat, else Nothing.

4 |> MinNat.isIntAtLeast nat5 --> Nothing


1234 |> MinNat.isIntAtLeast nat5 --> Just (NatIn 1234)
is :
NNat
(N
(Nat1Plus triedMinus1)
Is
(Difference (Nat1Plus aMinus1) To (Nat1Plus triedMinus1PlusA))
)
-> { min : NNat (N min Is (Difference lessRange To triedMinus1)) }
-> { equal : () -> result
, less : InNat min triedMinus1PlusA -> result
, greater : MinNat (Nat2Plus triedMinus1) -> result
}
-> MinNat min
-> result

Compared to an exact NNat.

NNat
(N
triedMin
Is
(Difference a To (Nat1Plus triedMinMinus1PlusA))
)
-> { min :
NNat (N min Is (Difference (Nat1Plus lessRange) To triedMin))
}
-> { less : InNat min triedMinMinus1PlusA -> result
, equalOrGreater : MinNat triedMin -> result
}
-> MinNat min
-> result

Is the MinNat

  • equalOrGreater than a NNat or

  • less?

factorialHelp : MinNat min -> MinNat Nat1
factorialHelp =
    MinNat.lowerMin nat0
        >> MinNat.isAtLeast nat1
            { min = nat0 }
            { less = \_ -> MinNat.n nat1
            , equalOrGreater =
                \oneOrGreater ->
                    oneOrGreater
                        |> MinNat.mul
                            (factorialHelp
                                (oneOrGreater |> MinNat.subN nat1)
                            )
            }
NNat (N atMostMin Is (Difference a To atMostMinPlusA))
-> { min : NNat (N min Is (Difference minToAtMostMin To atMostMin))
}
-> { equalOrLess : InNat min atMostMinPlusA -> result
, greater : MinNat atMostMin -> result
}
-> MinNat min
-> result

Is the MinNat

  • equalOrLess than a NNat or

  • greater?

drop information

toInt : MinNat min -> Int

Convert a MinNat to an Int.

MinNat.n nat4 |> MinNat.toInt --> 4


compare a b =
    compare (MinNat.toInt a) (MinNat.toInt b)
n : NNat (N n Is difference) -> MinNat n

Convert an exact NNat n to a MinNat n (n + a).

MinNat.n nat4
--> is of type MinNat Nat4 (Nat4Plus a)
NNat
(N
alsoValidmin
Is
(Difference currentMinusAlsoValidmin To min)
)
-> MinNat min
-> MinNat alsoValidmin

Set the minimum lower.

modify

NNat (N n Is (Difference min To minPlusN))
-> MinNat min
-> MinNat minPlusN

Add an exact NNat.

(nat5 |> MinNat.n)
    |> MinNat.addN nat2
--> MinNat 7
NNat (N n Is (Difference minMinusN To min))
-> MinNat min
-> MinNat minMinusN

Subtract an exact NNat.

(nat7 |> MinNat.n)
    |> MinNat.subN nat2
--> MinNat 5
add :
MinNat addedMin
-> NNat (N addedMin Is (Difference min To summin))
-> MinNat min
-> MinNat summin

Add a MinNat. The second argument is the minimum if the added MinNat.

(nat5 |> MinNat.n)
    |> MinNat.add atLeast2 nat2
InNat subtractedMin subtractedMax
-> NNat (N subtractedMax Is (Difference differenceMin To min))
-> MinNat min
-> MinNat differenceMin

Subtract a InNat. The second argument is the maximum if the subtracted InNat.

(nat5 |> MinNat.n)
    |> MinNat.subIn inNat0To5 itsMaximum
mul : MinNat (Nat1Plus multipliedMinMinus1) -> MinNat min -> MinNat min

Multiply by a MinNat >= 1. We can't compute the highest possiblenew minimum, we only know that if a >= 1 → x * a >= x

five |> MinNat.mul two
--> MinNat 10, but the type is MinNat Nat5


two |> MinNat.mul five
--> MinNat 10, but the type is MinNat Nat2


two = nat2 |> MinNat.n


five = nat5 |> MinNat.n
div : MinNat (Nat1Plus minMinus1) -> MinNat min -> MinNat Nat0

Divide (//) by a MinNat. div 0 is impossible.

MinNat.n nat7 |> MinNat.div (MinNat.n nat3)
--> MinNat 2 of type MinNat Nat0
remainderBy : MinNat (Nat1Plus dMinMinus1) -> MinNat min -> MinNat Nat0

The remainder after division. remainderBy 0 is impossible.

MinNat.n nat7 |> MinNat.remainderBy (MinNat.n nat3)
--> MinNat Nat0
toPower : MinNat (Nat1Plus minMinus1) -> MinNat min -> MinNat min

The MinNat ^ a MinNat. We can't compute the highest possible new minimum, we only know that if a >= 1 → x ^ a >= x

five |> MinNat.toPower two
--> MinNat 25, but the type is MinNat Nat5


two |> MinNat.mul five
--> MinNat 25, but the type is MinNat Nat2


two = nat2 |> MinNat.n


five = nat5 |> MinNat.n

extra

range : InNat firstMin lastMin -> MinNat lastMin -> List (MinNat firstMin)

MinNats from a first InNat to a last MinNat.