Floats & bytes
Partly builtThe float and bytes types: literals, arithmetic, conversion and the library calls that exist today.
Floats
float is a 64-bit IEEE 754 double. A literal has a decimal point (3.14159, 1.5e3, -0.0). The
arithmetic and comparison operators are shared with int: the checker resolves each use by type, and an operand that
could be either defaults to int. Mixing the two is a type error; convert explicitly.
let area = (r: float): float => 3.14159 * r * r
let half = (n: int): float => Float.fromInt(n) / 2.0
let root = Float.sqrt(16.0)The library is Float.fromInt, truncate, floor, ceil, round (half to even), sqrt, abs, toText, pow,
min, max, exp, log, logBase, the trigonometric and hyperbolic functions, atan2, and fromText (an
option<float>). Division by zero gives Infinity or NaN, never a failure.
Known limits, all recorded in docs/open-issues.md: the last digit of transcendental functions can differ between
UCM’s libm, the browser and the Rust engine, and a float to int conversion that overflows follows Unison’s saturate
and wrap rules rather than anything a language would pick for itself.
Nats
nat is Unison’s unsigned 64-bit natural number. The literal has an n suffix, 3n; a bare 3 stays an int, and
the two never mix (3n + 4 is a type error). +, *, / and the comparisons work on nats and wrap at 2^64.
There is no - on a nat (it would need a result that is sometimes negative): use Nat.sub(a, b), which gives an int,
or Nat.drop(a, b), which stops at 0.
let a = 3n + 4n // 7, shown as 7 (UCM shows a nat without a sign)
let b = Nat.toInt(a) + 1 // nat to int; Int.toNat(x) goes the other way, negatives become 0
let c = Nat.sub(2n, 5n) // -3, an int
let d = Nat.fromText("12") ?? 0n
Also available: Nat.mod, Nat.pow, Nat.toText, Nat.toFloat, Nat.increment, Nat.isEven, Nat.isOdd,
Int.fromNat, and for ints Int.signum, Int.increment, Int.isEven, Int.isOdd, Int.pow(base, exponent_nat),
Int.fromText. A nat is matched with the same suffix (| 0n => ...), and an int pattern may be negative (| -1 => ...); see Variants & switch.
Bytes
bytes holds a sequence of 8-bit values. The literal is 0xs"..." with an even number of hex digits (either case,
stored lowercase). == and the order operators compare lexicographically on unsigned bytes.
let blob = 0xs"0102ff"
let n = Bytes.size(blob)
let joined = Bytes.append(blob, 0xs"00")Also built: Bytes.empty(), Bytes.take(b, n), Bytes.drop(b, n), Bytes.at(b, i) (an option<int>) and
Bytes.toBase16(b), plus Bytes.fromBase16(b) (a result<string, bytes>, see Results). Bytes.empty() and the literal 0xs"" are different objects with different hashes.
Bytes patterns in switch are built too (| 0xs"0102" => ...).