mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Add some builtins
This commit is contained in:
parent
c90330cc4d
commit
f6ecc88d9c
5 changed files with 457 additions and 0 deletions
31
builtins/Bool.roc
Normal file
31
builtins/Bool.roc
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
api Bool provides Bool.*, not, equal, notEqual
|
||||||
|
|
||||||
|
## Either @True or @False.
|
||||||
|
Bool := False, True
|
||||||
|
|
||||||
|
## Returns @False when given @True, and vice versa.
|
||||||
|
not : Bool -> Bool
|
||||||
|
not = \bool ->
|
||||||
|
case bool when
|
||||||
|
False -> True
|
||||||
|
True -> False
|
||||||
|
|
||||||
|
## Returns @True if the two values are *structurally equal*, and @False otherwise.
|
||||||
|
##
|
||||||
|
## Structural equality works as follows:
|
||||||
|
##
|
||||||
|
## 1. @Int and @Float values are equal if their numbers are equal.
|
||||||
|
## 2. Records are equal if all their fields are equal.
|
||||||
|
## 3. Custom type variants (including the @True and @False variants of the @Bool custom type) are equal if they are the same variant, and also their contents (if any) are equal.
|
||||||
|
## 4. Collections (@String, @List, @Map, @Set, and @Bytes) are equal if they are the same length, and also all their corresponding elements are equal.
|
||||||
|
## 5. All functions are considered equal. (So `Bool.not == Bool.not` will return @True, as you might expect, but also `Num.abs == Num.negate` will return @True, as you might not. This design is because function equality has been formally proven to be undecidable in the general case, and returning @True in all cases turns out to be mostly harmless - especially compared to alternative designs like crashing, making @equal inconvenient to use, and so on.)
|
||||||
|
##
|
||||||
|
## This is the same as the @== operator.
|
||||||
|
eq : val, val -> Bool
|
||||||
|
|
||||||
|
## Calls @eq on the given values, then calls @not on the result.
|
||||||
|
##
|
||||||
|
## This is the same as the @=/= operator.
|
||||||
|
notEq : val, val -> Bool
|
||||||
|
notEq = \left right ->
|
||||||
|
not (equal left right)
|
164
builtins/Float.roc
Normal file
164
builtins/Float.roc
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
api Float provides Float, FloatingPoint
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
## A 64-bit floating-point number. All number literals with decimal points are @Float values.
|
||||||
|
##
|
||||||
|
## > 0.1
|
||||||
|
##
|
||||||
|
## > 1.0
|
||||||
|
##
|
||||||
|
## > 0.0
|
||||||
|
##
|
||||||
|
## If you like, you can put underscores in your @Float literals.
|
||||||
|
## They have no effect on the number's value, but can make things easier to read.
|
||||||
|
##
|
||||||
|
## > 1_000_000.000_000_001
|
||||||
|
##
|
||||||
|
## Unlike @Int values, @Float values are imprecise. A classic example of this imprecision:
|
||||||
|
##
|
||||||
|
## > 0.1 + 0.2
|
||||||
|
##
|
||||||
|
## Floating point values work this way because of some (very reasonable) hardware design decisions made in 1985, which are hardwired into all modern CPUs. The performance penalty for having things work any other way than this is severe, so Roc defaults to using the one with hardware support.
|
||||||
|
##
|
||||||
|
## It is possible to build fractional systems with different precision characteristics (for example, storing an @Int numerator and @Int denominator), but their basic arithmetic operations will be unavoidably slower than @Float.
|
||||||
|
##
|
||||||
|
## See @Float.highestSupported and @Float.lowestSupported for the highest and
|
||||||
|
## lowest values that can be held in a @Float.
|
||||||
|
##
|
||||||
|
## Note that although the IEEE-754 specification describes the values `Infinity`, `-Infinity`, `NaN`, and `-0.0`, Roc avoids these as follows:
|
||||||
|
##
|
||||||
|
## * @Float.sqrt returns `Err InvalidSqrt` when it would otherwise return `NaN`.
|
||||||
|
## * Division operations return `Err DivisionByZero` when they would otherwise return `Infinity` or `-Infinity`.
|
||||||
|
## * Operations that overflow crash (just like integers do) instead of returning `Infinity` or `-Infinity`.
|
||||||
|
## Under the hood, it is possible to have a zero @Float with a negative sign. However, this implementation detail intentionally conceealed. For equality purpose, `-0.0` is treated as equivalent to `0.0`, just like the spec prescribes. However, @Str.decimal always returns `0.0` when it would otherwise return `-0.0`, and both @Num.isPositive and @Num.isNegative return @False for all zero values. The only way to detect a zero with a negative sign is to convert it to @Bytes and inspect the bits directly.
|
||||||
|
Float : Num FloatingPoint
|
||||||
|
|
||||||
|
FloatingPoint := FloatingPoint
|
||||||
|
|
||||||
|
## Returned by @Float.sqrt when given a negative number.
|
||||||
|
InvalidSqrt := InvalidSqrt
|
||||||
|
|
||||||
|
## Conversions
|
||||||
|
|
||||||
|
fromNum : Num * -> Float
|
||||||
|
|
||||||
|
round : Float -> Int
|
||||||
|
|
||||||
|
ceiling : Float -> Int
|
||||||
|
|
||||||
|
floor : Float -> Int
|
||||||
|
|
||||||
|
## Trigonometry
|
||||||
|
|
||||||
|
cos : Float -> Float
|
||||||
|
|
||||||
|
acos : Float -> Float
|
||||||
|
|
||||||
|
sin : Float -> Float
|
||||||
|
|
||||||
|
asin : Float -> Float
|
||||||
|
|
||||||
|
tan : Float -> Float
|
||||||
|
|
||||||
|
atan : Float -> Float
|
||||||
|
|
||||||
|
## Other Calculations (arithmetic?)
|
||||||
|
|
||||||
|
## Divide two @Float numbers. Return `Err DivisionByZero` if the
|
||||||
|
## second number is zero, because division by zero is undefined in mathematics.
|
||||||
|
##
|
||||||
|
## (To divide an @Int and a @Float, first convert the @Int to a @Float using one of the functions in this module.)
|
||||||
|
##
|
||||||
|
## `a / b` is shorthand for `Float.div a b`.
|
||||||
|
##
|
||||||
|
## > 5.0 / 7.0
|
||||||
|
##
|
||||||
|
## > Float.div 5 7
|
||||||
|
##
|
||||||
|
## > 4.0 / -0.5
|
||||||
|
##
|
||||||
|
## > Float.div 4.0 -0.5
|
||||||
|
div : Float, Float -> Result Float DivisionByZero
|
||||||
|
|
||||||
|
## Perform modulo on two @Float numbers.
|
||||||
|
##
|
||||||
|
## Modulo is the same as remainder when working with positive numbers,
|
||||||
|
## but if either number is negative, then modulo works differently.
|
||||||
|
##
|
||||||
|
## Return `Err DivisionByZero` if the second number is zero, because division by zero is undefined in mathematics.
|
||||||
|
##
|
||||||
|
## `a % b` is shorthand for `Float.mod a b`.
|
||||||
|
##
|
||||||
|
## > 5.0 % 7.0
|
||||||
|
##
|
||||||
|
## > Float.mod 5 7
|
||||||
|
##
|
||||||
|
## > 4.0 % -0.5
|
||||||
|
##
|
||||||
|
## > Float.mod -8 -3
|
||||||
|
mod : Float, Float -> Result Float DivisionByZero
|
||||||
|
|
||||||
|
## Return the reciprocal of the @Float.
|
||||||
|
recip : Float -> Result Float Num.DivisionByZero
|
||||||
|
recip = \float ->
|
||||||
|
1.0 / float
|
||||||
|
|
||||||
|
## Return an approximation of the absolute value of the square root of the @Float.
|
||||||
|
##
|
||||||
|
## Return @InvalidSqrt if given a negative number. The square root of a negative number is an irrational number, and @Float only supports rational numbers.
|
||||||
|
##
|
||||||
|
## > Float.sqrt 4.0
|
||||||
|
##
|
||||||
|
## > Float.sqrt 1.5
|
||||||
|
##
|
||||||
|
## > Float.sqrt 0.0
|
||||||
|
##
|
||||||
|
## > Float.sqrt -4.0
|
||||||
|
sqrt : Float -> Result Float InvalidSqrt
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
## An approximation of e.
|
||||||
|
e : Float
|
||||||
|
e = 2... #TODO fill this in, and make the docs nicer!
|
||||||
|
|
||||||
|
## An approximation of pi.
|
||||||
|
pi : Float
|
||||||
|
pi = 3.14... #TODO fill this in, and make the docs nicer!
|
||||||
|
|
||||||
|
## Limits
|
||||||
|
|
||||||
|
## The highest supported @Float value you can have: [TODO put the number here]
|
||||||
|
##
|
||||||
|
## If you go higher than this, your running Roc code will crash - so be careful not to!
|
||||||
|
highestSupported : Float
|
||||||
|
|
||||||
|
## The lowest supported @Float value you can have: [TODO put the number here]
|
||||||
|
##
|
||||||
|
## If you go lower than this, your running Roc code will crash - so be careful not to!
|
||||||
|
lowestSupported : Float
|
||||||
|
|
||||||
|
## The highest integer that can be represented as a @Float without
|
||||||
|
## losing precision.
|
||||||
|
##
|
||||||
|
## Some integers higher than this can be represented, but they may lose precision. For example:
|
||||||
|
##
|
||||||
|
## > Float.highestLosslessInt
|
||||||
|
##
|
||||||
|
## > Float.highestLosslessInt + 100 # Increasing may lose precision
|
||||||
|
##
|
||||||
|
## > Float.highestLosslessInt - 100 # Decreasing is fine - but watch out for lowestLosslessInt!
|
||||||
|
highestLosslessInt : Float
|
||||||
|
|
||||||
|
## The lowest integer that can be represented as a @Float without
|
||||||
|
## losing precision.
|
||||||
|
##
|
||||||
|
## Some integers lower than this can be represented, but they may lose precision. For example:
|
||||||
|
##
|
||||||
|
## > Float.lowestLosslessInt
|
||||||
|
##
|
||||||
|
## > Float.lowestLosslessInt - 100 # Decreasing may lose precision
|
||||||
|
##
|
||||||
|
## > Float.lowestLosslessInt + 100 # Increasing is fine - but watch out for highestLosslessInt!
|
||||||
|
lowestLosslessInt : Float
|
89
builtins/Int.roc
Normal file
89
builtins/Int.roc
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
api Int provides Int, Integer
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
Integer := Integer
|
||||||
|
|
||||||
|
## A 64-bit signed integer. All number literals without decimal points are @Int values.
|
||||||
|
##
|
||||||
|
## > 1
|
||||||
|
##
|
||||||
|
## > 0
|
||||||
|
##
|
||||||
|
## You can optionally put underscores in your @Int literals.
|
||||||
|
## They have no effect on the number's value, but can make large numbers easier to read.
|
||||||
|
##
|
||||||
|
## > 1_000_000
|
||||||
|
##
|
||||||
|
## See @Int.highestSupported and @Int.lowestSupported for the highest and
|
||||||
|
## lowest values that can be held in an @Int.
|
||||||
|
Int : Num Integer
|
||||||
|
|
||||||
|
## Arithmetic
|
||||||
|
|
||||||
|
## Divide two integers and call @Float.floor on the result.
|
||||||
|
##
|
||||||
|
## (Use @Float.div for non-flooring division.)
|
||||||
|
##
|
||||||
|
## Return `Err DivisionByZero` if the second integer is zero, because division by zero is undefined in mathematics.
|
||||||
|
##
|
||||||
|
## `a // b` is shorthand for `Int.divFloor a b`.
|
||||||
|
##
|
||||||
|
## > 5 // 7
|
||||||
|
##
|
||||||
|
## > Int.divFloor 5 7
|
||||||
|
##
|
||||||
|
## > -8 // -3
|
||||||
|
##
|
||||||
|
## > Int.divFloor -8 -3
|
||||||
|
##
|
||||||
|
## This is the same as the @// operator.
|
||||||
|
divFloor : Int, Int -> Result DivisionByZero Int
|
||||||
|
|
||||||
|
## Perform flooring modulo on two integers.
|
||||||
|
##
|
||||||
|
## Modulo is the same as remainder when working with positive numbers,
|
||||||
|
## but if either number is negative, then modulo works differently.
|
||||||
|
##
|
||||||
|
## Additionally, flooring modulo uses @Float.floor on the result.
|
||||||
|
##
|
||||||
|
## (Use @Float.mod for non-flooring modulo.)
|
||||||
|
##
|
||||||
|
## Return `Err DivisionByZero` if the second integer is zero, because division by zero is undefined in mathematics.
|
||||||
|
##
|
||||||
|
## `a %% b` is shorthand for `Int.modFloor a b`.
|
||||||
|
##
|
||||||
|
## > 5 %% 7
|
||||||
|
##
|
||||||
|
## > Int.modFloor 5 7
|
||||||
|
##
|
||||||
|
## > -8 %% -3
|
||||||
|
##
|
||||||
|
## > Int.modFloor -8 -3
|
||||||
|
divFloor : Int, Int -> Result DivisionByZero Int
|
||||||
|
|
||||||
|
|
||||||
|
## Bitwise
|
||||||
|
|
||||||
|
bitwiseXor : Int -> Int -> Int
|
||||||
|
|
||||||
|
bitwiseAnd : Int -> Int -> Int
|
||||||
|
|
||||||
|
bitwiseNot : Int -> Int
|
||||||
|
|
||||||
|
## Limits
|
||||||
|
|
||||||
|
## The highest number that can be stored in an @Int without overflowing its
|
||||||
|
## available memory (64 bits total) and crashing.
|
||||||
|
##
|
||||||
|
## Note that this is smaller than the positive version of @Int.lowestSupported,
|
||||||
|
## which means if you call @Num.abs on @Int.lowestSupported, it will crash!
|
||||||
|
highestSupported : Int
|
||||||
|
|
||||||
|
## The lowest number that can be stored in an @Int without overflowing its
|
||||||
|
## available memory (64 bits total) and crashing.
|
||||||
|
##
|
||||||
|
## Note that the positive version of this number is this is larger than
|
||||||
|
## @Int.highestSupported, which means if you call @Num.abs on @Int.lowestSupported,
|
||||||
|
## it will crash!
|
||||||
|
lowestSupported : Int
|
126
builtins/Num.roc
Normal file
126
builtins/Num.roc
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
api Num provides Num, negate
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
Num range := Num range
|
||||||
|
|
||||||
|
## Returned by division operations (@Float.div, @Float.mod, @Int.divFloor, @Int.divMod, and @Float.recip) when they attempt to divide by zero.
|
||||||
|
DivisionByZero := DivisionByZero
|
||||||
|
|
||||||
|
## Convert
|
||||||
|
|
||||||
|
## Return a negative number when given a positive one, and vice versa.
|
||||||
|
##
|
||||||
|
## Some languages have a unary `-` operator (for example, `-(a + b)`), but Roc does not. If you want to negate a number, calling this function is the way to do it!
|
||||||
|
##
|
||||||
|
## > Num.negate 5
|
||||||
|
##
|
||||||
|
## > Num.negate -2.5
|
||||||
|
##
|
||||||
|
## > Num.negate 0
|
||||||
|
##
|
||||||
|
## > Num.negate 0.0
|
||||||
|
##
|
||||||
|
## This will crash when given @Int.lowestValue, because doing so will result in a number higher than @Int.highestValue.
|
||||||
|
##
|
||||||
|
## (It will never crash when given a @Float, however, because of how floating point numbers represent positive and negative numbers.)
|
||||||
|
negate : 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.
|
||||||
|
##
|
||||||
|
## > Num.abs 4
|
||||||
|
##
|
||||||
|
## > Num.abs -2.5
|
||||||
|
##
|
||||||
|
## > Num.abs 0
|
||||||
|
##
|
||||||
|
## > Num.abs 0.0
|
||||||
|
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
|
||||||
|
##
|
||||||
|
## > 3.0 + -0.5
|
||||||
|
##
|
||||||
|
## > Num.add 3.0 -0.5
|
||||||
|
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
|
||||||
|
##
|
||||||
|
## > 3.0 - -0.5
|
||||||
|
##
|
||||||
|
## > Num.sub 3.0 -0.5
|
||||||
|
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
|
||||||
|
##
|
||||||
|
## > 4.0 * -0.5
|
||||||
|
##
|
||||||
|
## > Num.mul 4.0 -0.5
|
||||||
|
mul : Num range, Num range -> Num range
|
47
builtins/Str.roc
Normal file
47
builtins/Str.roc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
api Str provides Str, isEmpty, join
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
Str := Str
|
||||||
|
|
||||||
|
## Convert
|
||||||
|
|
||||||
|
## Convert a @Float to a decimal string, rounding off to the given number of decimal places.
|
||||||
|
##
|
||||||
|
## Since @Float values are imprecise, it's usually best to limit this to the lowest
|
||||||
|
## number you can choose that will make sense for what you want to display.
|
||||||
|
##
|
||||||
|
## If you want to kep all the digits, passing @Int.highestSupported will accomplish this,
|
||||||
|
## but it's recommended to pass much smaller numbers instead.
|
||||||
|
##
|
||||||
|
## Passing a negative number for decimal places is equivalent to passing 0.
|
||||||
|
decimal : Int, Float -> Str
|
||||||
|
|
||||||
|
## Convert an @Int to a string.
|
||||||
|
int : Float -> Str
|
||||||
|
|
||||||
|
## Check
|
||||||
|
|
||||||
|
isEmpty : Str -> Bool
|
||||||
|
|
||||||
|
startsWith : Str, Str -> Bool
|
||||||
|
|
||||||
|
endsWith : Str, Str -> Bool
|
||||||
|
|
||||||
|
contains : Str, Str -> Bool
|
||||||
|
|
||||||
|
any : Str, Str -> Bool
|
||||||
|
|
||||||
|
all : Str, Str -> Bool
|
||||||
|
|
||||||
|
## Combine
|
||||||
|
|
||||||
|
join : List Str -> Str
|
||||||
|
|
||||||
|
joinWith : Str, List Str -> Str
|
||||||
|
|
||||||
|
padStart : Int, Str, Str -> Str
|
||||||
|
|
||||||
|
padEnd : Int, Str, Str -> Str
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue