Stream: show and tell

Topic: Roc Math(s)


view this post on Zulip Hannes (Jun 27 2023 at 05:22):

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.

view this post on Zulip Hannes (May 14 2024 at 03:06):

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: )

view this post on Zulip Isaac Van Doren (May 14 2024 at 03:35):

That's great!

view this post on Zulip Isaac Van Doren (May 14 2024 at 03:36):

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?

view this post on Zulip Hannes (May 14 2024 at 04:41):

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:

view this post on Zulip Hannes (May 14 2024 at 04:56):

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."

view this post on Zulip Hannes (Feb 09 2025 at 07:17):

roc-math v0.5.0 adds support for Roc v0.0.0-alpha2 :)


Last updated: Jul 06 2025 at 12:14 UTC