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 U16s 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 Gens and Tasks 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: Nov 28 2025 at 12:16 UTC