Skip to content

Instantly share code, notes, and snippets.

@tonymorris
Last active December 17, 2015 18:48
Show Gist options
  • Save tonymorris/5655357 to your computer and use it in GitHub Desktop.
Save tonymorris/5655357 to your computer and use it in GitHub Desktop.
How to produce random function values (Rng[B => A])?
sealed trait RngOp[A] {
def map[B](f: A => B): RngOp[B] =
this match {
case NextBits(b, n) => NextBits(b, f compose n)
case SetSeed(b, n) => SetSeed(b, () => f(n()))
}
def lift: Rng[A] =
Cont(map(Done(_)))
}
case class NextBits[A](b: Int, n: Int => A) extends RngOp[A]
case class SetSeed[A](b: Long, n: () => A) extends RngOp[A]
sealed trait Rng[A] {
def map[B](f: A => B): Rng[B] =
this match {
case Done(a) => Done(f(a))
case Cont(r) => Cont(r map (_ map f))
}
def flatMap[B](f: A => Rng[B]): Rng[B] =
this match {
case Done(a) => f(a)
case Cont(r) => Cont(r map (_ flatMap f))
}
def function[B]: Rng[B => A] =
sys.error("what to do here?")
// Is Rng[A] => Rng[B => A] even sensible?
// What about other ways to produce Rng[B => A] values?
// map(a => _ => a) // ick!
// Can it be done with a constraint on B?
// such as Corng?
def functionAttemptWithCoRng[B](c: Corng[B]): Rng[B => A] =
sys.error("??")
}
case class Done[A](a: A) extends Rng[A]
case class Cont[A](r: RngOp[Rng[A]]) extends Rng[A]
object Rng {
def nextbits(n: Int): Rng[Int] =
NextBits(n, x => x).lift
def setseed(s: Long): Rng[Unit] =
SetSeed(s, () => ()).lift
def int: Rng[Int] =
nextbits(32)
def chooseint(l: Int, h: Int): Rng[Int] =
int map (x => {
val (ll, hh) = if(h < l) (h, l) else (l, h)
ll + math.abs(x % (hh - ll + 1))
})
def long: Rng[Long] =
for {
a <- nextbits(32)
b <- nextbits(32)
} yield (a.toLong << 32) + b
}
trait Corng[A] {
def run[B](a: A, r: Rng[B]): Rng[B]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment