https://github.com/evolution-gaming/random
Pure random number generator
https://github.com/evolution-gaming/random
cats random rng scala
Last synced: 2 months ago
JSON representation
Pure random number generator
- Host: GitHub
- URL: https://github.com/evolution-gaming/random
- Owner: evolution-gaming
- License: mit
- Created: 2019-03-06T20:27:51.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2025-03-18T12:07:43.000Z (4 months ago)
- Last Synced: 2025-04-23T00:15:44.133Z (2 months ago)
- Topics: cats, random, rng, scala
- Language: Scala
- Size: 153 KB
- Stars: 4
- Watchers: 10
- Forks: 3
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Random
[](https://github.com/evolution-gaming/random/actions?query=workflow%3ACI)
[](https://coveralls.io/r/evolution-gaming/random)
[](https://app.codacy.com/gh/evolution-gaming/random/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[](https://evolution.jfrog.io/ui/packages/gav:%2F%2Fcom.evolution:random_2.13)
[](https://opensource.org/licenses/MIT)Pure deterministic pseudo-random number generator, which returns a new state on each call.
The returned state could be used to generate a next random value, without
relying for it to be saved in a mutable variable inside of the RNG library.It could be useful for writing the code, when the direct usage of an effect
system such as `cats.effect.IO` is either not possible or not desired. Also,
the versions `0.1.1` and below are compatible with Cats Effect 2.If the application already uses Cats Effect 3 and pure random generator is not
required then https://typelevel.org/cats-effect/docs/std/random might be a
preferred choice for sake of using a more standard solution.```scala
trait Random[F[_]] {def int: F[Int]
def long: F[Long]
def float: F[Float]
def double: F[Double]
}
```## Setup
```scala
addSbtPlugin("com.evolution" % "sbt-artifactory-plugin" % "0.0.2")libraryDependencies += "com.evolution" %% "random" % "1.0.5"
```## Usage
The library could be used directly with pure Scala without any additional effect systems:
```scala
def currentTimeSeedExample(): Unit = {
// note, that current time could be a bad choice for a seed
val state0 = Random.State(System.currentTimeMillis())
val (state1, n0) = state0.int
val (_, n1) = state1.int
println(s"Two random numbers: $n0, $n1")
}
```It also includes facilities to create a random number generator with a safe seed based on the current time from Cats Effect `Clock` instance:
```scala
def clockSeedExample: IO[Unit] =
for {
state0 <- Random.State.fromClock[IO]()
(state1, n0) = state0.int
(_, n1) = state1.int
_ <- IO.println(s"Two random numbers: $n0, $n1")
} yield ()
```The typical Cats Effect user might prefer storing these instances in `IOLocal`
for efficiency and code readability (i.e. to not pass a state manually around):``` scala
def ioLocalExample: IO[Unit] =
for {
random <- IOLocalRandom.fromClock
n0 <- random.int
n1 <- random.int
_ <- IO.println(s"Two random numbers: $n0, $n1")
} yield ()
object IOLocalRandom {def fromClock: IO[Random[IO]] =
for {
random <- Random.State.fromClock[IO]()
random <- IOLocal(random)
} yield new Random[IO] {
def int: IO[Int] = random.modify(_.int)
def long: IO[Long] = random.modify(_.long)
def float: IO[Float] = random.modify(_.float)
def double: IO[Double] = random.modify(_.double)
}}
```It is also possible to use the same approach in a Tagless Final environment
using `ThreadLocalOf` from Cats Helper library:```scala
import com.evolutiongaming.catshelper.ThreadLocalOfdef threadLocalExample[F[_]: Monad: Clock: Console: ThreadLocalOf]: F[Unit] =
for {
random <- ThreadLocalRandom.fromClock[F]
n0 <- random.int
n1 <- random.int
_ <- Console[F].println(s"Two random numbers: $n0, $n1")
} yield ()object ThreadLocalRandom {
def fromClock[F[_]: Monad: Clock: ThreadLocalOf]: F[Random[F]] =
for {
random <- Random.State.fromClock[F]()
random <- ThreadLocalOf[F].apply(random)
} yield new Random[F] {
def int: F[Int] = random.modify(_.int)
def long: F[Long] = random.modify(_.long)
def float: F[Float] = random.modify(_.float)
def double: F[Double] = random.modify(_.double)
}}
```