I'm new to Roc with a numerics background. I'm used to things like 1.0 / 0.0 being Infinity and 0.0 / 0.0 being NaN. Does Roc use IEEE754 floating point arithmetic? Is it defaulting to the decimal type? (And is the decimal type supposed to be a floating-point value with decimal digits (mantissa) instead of binary digits? Or an integer with fixed point semantics?)
Default fractional type is a fixed point decimal
Can just specify the type to get a float though
1.0f32 / 0.0
also type inference takes care of that automatically; if you have a function that expects a F64
or F32
, you can pass it 1.0
or even just 1
and it will use the appropriate representation
Awesome - thanks, that makes a lot of sense.
Is there any syntax (i.e. literals) for Infinity, -Infinity and NaN of F32 and F64? The printing of these values at the REPL isn't round-trippable.
I don't there is. I'm interested to know what round-trippable means?
I assume as in what the repl prints out can't be put back into the program
we should probably make Num.infinityF32
and Num.infinityF64
and same for nan
we can't give them the type Frac *
because Dec
doesn't have infinity and nan
also probably don't need a negative infinity because e.g. -Num.infinityF64
would compile to that anyway
Yes I meant what printed in the REPL for at least built-in primitive types like F64 and F32 should be valid syntax for the same value. (In fact, for a functional language it should be possible to ensure this for basically all values, though you might not want to print everything in full at the REPL by default).
Note that being round-trippable for finite floating-point numbers is also pretty big deal. Back in the 2000's, say, a lot of languages would not give the exact same float when you print it and then parse it again, which causes trouble for really basic interchange like saving and loading a CSV or trying to debug a problem or whatever. Nowadays there exist fast and robust techniques for printing and parsing floats, so that shouldn't be a problem, but I didn't look into how Roc does this yet.
Richard Feldman said:
also probably don't need a negative infinity because e.g.
-Num.infinityF64
would compile to that anyway
I'd suggest following whatever Roc does for -1.0. Is that evaluated as -(1.0) or parsed as a single literal?
made an issue! https://github.com/roc-lang/roc/issues/6709
Andy Ferris said:
Yes I meant what printed in the REPL for at least built-in primitive types like F64 and F32 should be valid syntax for the same value. (In fact, for a functional language it should be possible to ensure this for basically all values, though you might not want to print everything in full at the REPL by default).
in the case of opaque types it's very important that this property not hold, and for functions it's probably more annoying than helpful (especially long functions), but yeah for structural types other than functions I agree!
I've made a little bit more progress on this at https://github.com/roc-lang/roc/pull/6755, but am a little stuck.
Part of my problem is now cargo build
isn't working (on WSL2) as it is complaining about the llvm-sys
crate not being able to find LLVM. I tried apt installing llvm-dev
but that wasn't helpful. The end result is I haven't been able to run my changes locally.
This may help:
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 16
Add export LLVM_SYS_160_PREFIX=/usr/lib/llvm-16
to your ~/.bashrc
or equivalent file for your shell.
Although I would recommend using nix with nix develop
as that will set up everything for you.
Thanks that helps. I also had to install libpolly-16-dev and libzstd-dev.
I tried nix develop
and it originally worked (a couple of weeks ago) but now it isn't, not sure what I've done differently.
I tried
nix develop
and it originally worked (a couple of weeks ago) but now it isn't, not sure what I've done differently.
You may need to do cargo clean
because problems arise when rust tries to combine old cached build artifacts (outside nix) with new ones built inside nix.
Last updated: Jul 06 2025 at 12:14 UTC