Skip to content

Instantly share code, notes, and snippets.

@danwerner
Last active February 19, 2021 14:10
Show Gist options
  • Save danwerner/d7a6703bb485d973b85d01f883668b1c to your computer and use it in GitHub Desktop.
Save danwerner/d7a6703bb485d973b85d01f883668b1c to your computer and use it in GitHub Desktop.
How to use the Numeric/Integral typeclasses in Scala
package com.example.stubs
import scala.Integral.Implicits._
import scala.Ordering.Implicits._
abstract class NumericStub[N : Integral] {
/**
* Returns the next pseudo-random number of type `N`.
*/
def nextRandom(): N
/**
* Returns the next pseudo-random number of type `N`
* between zero (inclusive) and `upperBound` (exclusive).
*/
def nextRandom(upperBound: N): N
def randomPositive: N = nextRandom().abs
def randomInRange(low: N, high: N): N = {
// Integral extends Numeric, which extends Ordering. Therefore,
// comparison operators are automatically available.
require(low < high)
val random = randomPositive
// Numeric provides +, -, *, …
val rangeLength = high - low
// Integral provides / and %
val selectedInRangeLength = random % rangeLength
low + selectedInRangeLength
}
}
package com.example.stubs
import scala.util.Random
object IntStub extends IntegralStub[Int] {
override def nextRandom(): Int = Random.nextInt()
override def nextRandom(upperBound: Int): Int = Random.nextInt(upperBound)
}
package com.example.stubs
import scala.util.Random
object LongStub extends IntegralStub[Long] {
override def nextRandom(): Long = Random.nextLong()
// HACK: This can be done better
override def nextRandom(upperBound: Long): Long = IntStub.nextRandom(upperBound.toInt).toLong
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment