I'm looking to try some statistical/mathematical stuff in Roc in the future, so I've been slowly adding functions to a maths package for a while, it's in a state now where it's documented enough that I can release it. As usual I'm open to any feedback or PRs :)
Here's the repo: https://github.com/Hasnep/roc-math and the docs: https://hasnep.github.io/roc-math/
And an example app that does some calculations.
app "example"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br",
math: "https://github.com/Hasnep/roc-math/releases/download/v0.0.1/7Yv7iomNIZib-liFOqrf2TU5JlPFGsxgUawQ7cBx3ns.tar.br",
}
imports [pf.Stdout, math.Combinatorics.{ choose }, math.Stats.{ variance }, math.Const.{ π }]
provides [main] to pf
nChooseKMessage =
# Calculate
k = 10
n = 5
nChooseK = choose k n
# Output
kStr = Num.toStr k
nStr = Num.toStr n
nChooseKStr = Num.toStr nChooseK
"There are \(nChooseKStr) ways of choosing \(kStr) things from a collection of size \(nStr)."
varianceMessage =
start = 1
end = 10
when List.range { start: At start, end: At end } |> variance is
Ok v ->
startStr = Num.toStr start
endStr = Num.toStr end
varianceStr = Num.toStr v
"The unbiased sample variance of the numbers from \(startStr) to \(endStr) is \(varianceStr)."
Err ListWasEmpty -> "The variance of an empty list is undefined!"
circleMessage =
radius = 6
area = π * (radius ^ 2)
radiusStr = Num.toStr radius
areaStr = Num.toStr area
"The area of a pizza with radius \(radiusStr) is \(areaStr)."
main =
[nChooseKMessage, varianceMessage, circleMessage] |> Str.joinWith "\n" |> Stdout.line
and outputs:
There are 252 ways of choosing 10 things from a collection of size 5.
The unbiased sample variance of the numbers from 1 to 10 is 9.166666666666666.
The area of a pizza with radius 6 is 113.09733552923255.
Just wanted to announce that I've released v0.2.0 of roc-math, where I'm experimenting with an Angle
type.
An Angle
is one of [Radians F64, Degrees F64, Turns F64, Gon F64]
, and the Trig
functions all take an Angle
, e.g. Trig.sin (Degrees 90)
.
This lets you use degrees or turns in a type-safe way. (Or gradians/gon if that's your thing, no judgement :wink: )
That's great!
What's the motivation for having atan, acos, and asin take in the [ToTurns, ToRadians...] union instead of just picking a default for those functions?
No good reason, I was just experimenting and implemented the first API that came to my head :sweat_smile: I want to try using it in a project and see how it feels to use.
Having thought about it for more than a few seconds, it might be a situation where module parameters can make the API much simpler :shrug:
I forgot to add an example of the new API in my original message, it looks like this:
θ = Degrees 45
x = Trig.sin θ
Stdout.line! "sin of $(Angle.toStr θ) degrees is $(Num.toStr x)."
θₜ = Trig.asin x ToTurns
Stdout.line! "asin of $(Num.toStr x) is $(Angle.toStr θₜ) turns."
roc-math v0.5.0 adds support for Roc v0.0.0-alpha2 :)
Last updated: Jul 06 2025 at 12:14 UTC