splitting this off from https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/.E2.9C.94.20randomness.20in.20Task as a note about an API design idea in the future where we have module params
in that world, we can have a randomness package with two modules:
Gen
, which doesn't have any module params, and which describes everything in terms of generators and seeds - e.g. Gen.u16 1 1000
might give you back a Gen U16
that generates U16
s between 1 and 1000Random
, which takes a module param of secureSeed : Task U64 *
that platforms must provide (it should provide high-quality randomness, e.g. from /dev/random
), and which offers task-based randomness - e.g. Random.generate : Gen a -> Task a *
, and then also convenience functions like Random.u16 1 1000
which gives you back a Task U16 *
that you can run without providing a seed (because the task will automatically go ask the platform for a seed)this solves the problem of "chaining together a mix of interleaved Gen
s and Task
s does not work nicely" by giving Gen
a way to be wrapped in Task
also it means beginners who don't necessarily want to use Gen
can just use the Random.u16
convenience functions (which are slower, because they have to go to the OS each time to get randomness, and also they require a Task
, and also they are not reproducible using a Seed
- all of which are reasons to learn Gen
later!) because at first they probably know how tasks work and just want to get a random number or something.
cc @Fletch Canny since I saw you mentioned you've been porting a randomness library from Elm!
Last updated: Jul 06 2025 at 12:14 UTC