mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
187 lines
6.6 KiB
Text
187 lines
6.6 KiB
Text
interface Num
|
|
exposes [ Num, neg, abs, add, sub, mul, isOdd, isEven, isPositive, isNegative, isZero ]
|
|
imports []
|
|
|
|
## Types
|
|
|
|
## Represents a number that could be either an #Int or a #Float.
|
|
##
|
|
## This is useful for functions that can work on either, for example #Num.add, whose type is:
|
|
##
|
|
## ```
|
|
## add : Num range, Num range -> Num range
|
|
## ```
|
|
##
|
|
## The number 1.5 technically has the type `Num FloatingPoint`, so when you pass two of them to `Num.add`, the answer you get is `3.0 : Num FloatingPoint`.
|
|
##
|
|
## The type #Float is defined to be an alias for `Num FloatingPoint`, so `3.0 : Num FloatingPoint` is the same answer as `3.0 : Float`. # # Similarly, the number 1 technically has the type `Num Integer`, so when you pass two of them to `Num.add`, the answer you get is `2 : Num Integer`. # # The type #Int is defined to be an alias for `Num Integer`, so `2 : Num Integer` is the same answer as `2 : Int`. #
|
|
## In this way, the `Num` type makes it possible to have `1 + 1` return `2 : Int` and `1.5 + 1.5` return `3.0 : Float`.
|
|
##
|
|
## ## Number Literals
|
|
##
|
|
## Number literals without decimal points (like `0`, `4` or `360`)
|
|
## have the type `Num *` at first, but usually end up taking on
|
|
## a more specific type based on how they're used.
|
|
##
|
|
## For example, in `(1 + List.len myList)`, the `1` has the type `Num *` at first,
|
|
## but because `List.len` returns a `Ulen`, the `1` ends up changing from
|
|
## `Num *` to the more specific `Ulen`, and the expression as a whole
|
|
## ends up having the type `Ulen`.
|
|
##
|
|
## Sometimes number literals don't become more specific. For example,
|
|
## the #Num.toStr function has the type `Num * -> Str`. This means that
|
|
## when calling `Num.toStr (5 + 6)`, the expression `(5 + 6)`
|
|
## still has the type `Num *`. When this happens, `Num *` defaults to
|
|
## being an #I32 - so this addition expression would overflow
|
|
## if either 5 or 6 were replaced with a number big enough to cause
|
|
## addition overflow on an #I32.
|
|
##
|
|
## If this default of #I32 is not big enough for your purposes,
|
|
## you can add an `i64` to the end of the number literal, like so:
|
|
##
|
|
## >>> Num.toStr 5_000_000_000i64
|
|
##
|
|
## This `i64` suffix specifies that you want this number literal to be
|
|
## an #I64 instead of a `Num *`. All the other numeric types have
|
|
## suffixes just like `i64`; here are some other examples:
|
|
##
|
|
## * `215u8` is a `215` value of type #U8
|
|
## * `76.4f32` is a `76.4` value of type #F32
|
|
## * `12345ulen` is a `12345` value of type `#Ulen`
|
|
##
|
|
## In practice, these are rarely needed. It's most common to write
|
|
## number literals without any suffix.
|
|
Num range : @Num range
|
|
|
|
## Convert
|
|
|
|
## Return a negative number when given a positive one, and vice versa.
|
|
##
|
|
## >>> Num.neg 5
|
|
##
|
|
## >>> Num.neg -2.5
|
|
##
|
|
## >>> Num.neg 0
|
|
##
|
|
## >>> Num.neg 0.0
|
|
##
|
|
## This is safe to use with any #Float, but it can cause overflow when used with certain #Int values.
|
|
##
|
|
## For example, calling #Num.neg on the lowest value of a signed integer (such as #Int.lowestI64 or #Int.lowestI32) will cause overflow.
|
|
## This is because, for any given size of signed integer (32-bit, 64-bit, etc.) its negated lowest value turns out to be 1 higher than
|
|
## the highest value it can represent. (For this reason, calling #Num.abs on the lowest signed value will also cause overflow.)
|
|
##
|
|
## Additionally, calling #Num.neg on any unsigned integer (such as any #U64 or #U32 value) other than 0 will cause overflow.
|
|
##
|
|
## (It will never crash when given a #Float, however, because of how floating point numbers represent positive and negative numbers.)
|
|
neg : Num range -> Num range
|
|
|
|
## Return the absolute value of the number.
|
|
##
|
|
## * For a positive number, returns the same number.
|
|
## * For a negative number, returns the same number except positive.
|
|
## * For zero, returns zero.
|
|
##
|
|
## >>> Num.abs 4
|
|
##
|
|
## >>> Num.abs -2.5
|
|
##
|
|
## >>> Num.abs 0
|
|
##
|
|
## >>> Num.abs 0.0
|
|
##
|
|
## This is safe to use with any #Float, but it can cause overflow when used with certain #Int values.
|
|
##
|
|
## For example, calling #Num.abs on the lowest value of a signed integer (such as #Int.lowestI64 or #Int.lowestI32) will cause overflow.
|
|
## This is because, for any given size of signed integer (32-bit, 64-bit, etc.) its negated lowest value turns out to be 1 higher than
|
|
## the highest value it can represent. (For this reason, calling #Num.neg on the lowest signed value will also cause overflow.)
|
|
##
|
|
## Calling this on an unsigned integer (like #U32 or #U64) never does anything.
|
|
abs : Num range -> Num range
|
|
|
|
## Check
|
|
|
|
## The same as using `== 0` on the number.
|
|
isZero : Num * -> Bool
|
|
|
|
## Positive numbers are greater than 0.
|
|
isPositive : Num * -> Bool
|
|
|
|
## Negative numbers are less than 0.
|
|
isNegative : Num * -> Bool
|
|
|
|
## A number is even if dividing it by 2 gives a remainder of 0.
|
|
##
|
|
## Examples of even numbers: 0, 2, 4, 6, 8, -2, -4, -6, -8
|
|
isEven : Num * -> Bool
|
|
|
|
## A number is odd if dividing it by 2 gives a remainder of 1.
|
|
##
|
|
## Examples of odd numbers: 1, 3, 5, 7, -1, -3, -5, -7
|
|
isOdd : Num * -> Bool
|
|
|
|
## Arithmetic
|
|
|
|
## Add two numbers of the same type.
|
|
##
|
|
## (To add an #Int and a #Float, first convert one so that they both have the same type. There are functions in the [`Float`](/Float) module that can convert both #Int to #Float and the other way around.)
|
|
##
|
|
## `a + b` is shorthand for `Num.add a b`.
|
|
##
|
|
## >>> 5 + 7
|
|
##
|
|
## >>> Num.add 5 7
|
|
##
|
|
## `Num.add` can be convenient in pipelines.
|
|
##
|
|
## >>> Float.pi
|
|
## >>> |> Num.add 1.0
|
|
add : Num range, Num range -> Num range
|
|
|
|
## Subtract two numbers of the same type.
|
|
##
|
|
## (To subtract an #Int and a #Float, first convert one so that they both have the same type. There are functions in the [`Float`](/Float) module that can convert both #Int to #Float and the other way around.)
|
|
##
|
|
## `a - b` is shorthand for `Num.sub a b`.
|
|
##
|
|
## >>> 7 - 5
|
|
##
|
|
## >>> Num.sub 7 5
|
|
##
|
|
## `Num.sub` can be convenient in pipelines.
|
|
##
|
|
## >>> Float.pi
|
|
## >>> |> Num.sub 2.0
|
|
sub : Num range, Num range -> Num range
|
|
|
|
## Multiply two numbers of the same type.
|
|
##
|
|
## (To multiply an #Int and a #Float, first convert one so that they both have the same type. There are functions in the [`Float`](/Float) module that can convert both #Int to #Float and the other way around.)
|
|
##
|
|
## `a * b` is shorthand for `Num.mul a b`.
|
|
##
|
|
## >>> 5 * 7
|
|
##
|
|
## >>> Num.mul 5 7
|
|
##
|
|
## `Num.mul` can be convenient in pipelines.
|
|
##
|
|
## >>> Float.pi
|
|
## >>> |> Num.mul 2.0
|
|
mul : Num range, Num range -> Num range
|
|
|
|
## Convert
|
|
|
|
## Convert a number to a string, formatted as the traditional base 10 (decimal).
|
|
##
|
|
## >>> Num.toStr 42
|
|
##
|
|
## Only #Float values will show a decimal point, and they will always have one.
|
|
##
|
|
## >>> Num.toStr 4.2
|
|
##
|
|
## >>> Num.toStr 4.0
|
|
##
|
|
## For other bases see #toHexStr, #toOctalStr, and #toBinaryStr.
|
|
toStr : Num * -> Str
|
|
|