Skip to content

Instantly share code, notes, and snippets.

@leifwickland
Created November 7, 2018 17:12
Show Gist options
  • Save leifwickland/c3bcdb6cd2fa533a5780140e07d03fa6 to your computer and use it in GitHub Desktop.
Save leifwickland/c3bcdb6cd2fa533a5780140e07d03fa6 to your computer and use it in GitHub Desktop.
Refined percentage
/// A double floating point number which allows values in the range [0.0,100.0].
object ProperPercentage {
type L = W.`0.0`.T
type H = W.`100.0`.T
type P = Interval.Closed[L, H]
type N = Double
type T = N Refined P
val gen: Gen[Refined[N, Closed[L, H]]] = intervalClosedArbitrary[Refined, N, L, H].arbitrary
def safely(d: Double): String \/ T = refineV[P].apply(d).fold(_.left, _.right)
def unsafe(d: Double): T = safely(d).valueOr(m => throw new Exception(m))
val Zero: T = unsafe(0.0)
val OneHundred: T = unsafe(100.0)
def asFraction(p: T): Double = p.value / 100.0
def fromFraction(d: Double): String \/ T = safely(d * 100D)
}
/**
* Add `refine` and `unsafe` to the companion object of a class which is a simple wrapper around `ProperPercentage.T`.
*/
trait ProperPercentageWrapper {
type W
val wrap: ProperPercentage.T => W
def safely(d: Double): String \/ W = ProperPercentage.safely(d).map(wrap)
def unsafe(d: Double): W = safely(d).valueOr(m => throw new Exception(m))
def unwrap(w: W): ProperPercentage.T
implicit val orderingW: Ordering[W] = Ordering.by(w => unwrap(w).value)
implicit val orderW: Order[W] = Order.fromScalaOrdering(orderingW)
}
case class SampleRate(r: ProperPercentage.T)
object SampleRate extends ProperPercentageWrapper {
type W = SampleRate
val wrap: T => SampleRate = SampleRate.apply
def unwrap(w: SampleRate): T = w.r
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment