Random
A purely-functional implementation of a source of random information.
trait Random[F[_]] {
def nextInt: F[Int]
def shuffleList[A](list: List[A]): F[List[A]]
// ... and more
}
API
The API of Random is created to closely resemble the scala.util.Random API,
so it should be fairly approachable to people familiar with the
standard library.
Users can expect to find all methods available on a Scala standard library
Random instance also available on instances of this type class (with some
minor renamings to avoid method overloading, e.g. betweenLong,
betweenDouble, etc).
Customizing the source of randomness
cats.effect.std.Random can be backed by a variety of random sources available
on the JVM:
scala.util.Random(Random.scalaUtilRandom[F: Sync])- Individual instances can be customized with an initial seed, or load
balanced between several
scala.util.Randominstances
- Individual instances can be customized with an initial seed, or load
balanced between several
java.util.Randomjava.security.SecureRandom
Creating a Random instance
Obtaining an instance of Random can be as simple as:
import cats.effect.IO
import cats.effect.std.Random
Random.scalaUtilRandom[IO]
Using Random
import cats.effect.std.{Console, Random, SecureRandom}
import cats.{Functor, FlatMap}
import cats.syntax.all.toFlatMapOps
import cats.syntax.all.toFunctorOps
def dieRoll[F[_] : Functor : Random]: F[Int] =
Random[F].betweenInt(0, 6).map(_ + 1)
// Scala 2.x & 3.x
def showMagicNumber[F[_] : Console : FlatMap](id: String, rnd: F[Random[F]]): F[Unit] =
rnd.flatMap(implicit rnd => dieRoll[F].flatMap(i => Console[F].println(s"$id: $i")))
/* Scala 2.x with better-monadic-for compiler plugin
def showMagicNumber_bmf[F[_] : Console : FlatMap](id: String, rnd: F[Random[F]]): F[Unit] =
for {
implicit0(it: Random[F]) <- rnd
i <- dieRoll[F]
_ <- Console[F].println(s"$id: $i")
} yield ()
*/
/* Scala 3.x only
def showMagicNumber3[F[_] : Console : FlatMap](id: String, rnd: F[Random[F]]): F[Unit] =
for {
given Random[F] <- rnd
i <- dieRoll[F]
_ <- Console[F].println(s"$id: $i")
} yield ()
*/
val app = showMagicNumber("rnd", Random.scalaUtilRandom[IO]) *>
showMagicNumber[IO]("sec-rnd", SecureRandom.javaSecuritySecureRandom[IO])
// app: IO[Unit] = FlatMap(
// ioe = FlatMap(
// ioe = Delay(
// thunk = cats.effect.std.Random$$$Lambda$18897/0x00007f2de3127a50@2f0b2e52,
// event = cats.effect.tracing.TracingEvent$StackTrace
// ),
// f = <function1>,
// event = cats.effect.tracing.TracingEvent$StackTrace
// ),
// f = cats.effect.IO$$Lambda$18234/0x00007f2de2e0c7a0@181fa615,
// event = cats.effect.tracing.TracingEvent$StackTrace
// )
// required for unsafeRunSync()
import cats.effect.unsafe.implicits.global
app.unsafeRunSync()
Derivation
An instance of cats.effect.std.Random can be created by any data type
capable of synchronously suspending side effects (i.e. Sync). Furthermore,
Random instances for monad transformers can be automatically derived for any
data type for which an instance of Random can already be derived.