Last active
March 31, 2020 20:49
-
-
Save johnynek/2432e2e61221cbf9e56fc4d784c3fac7 to your computer and use it in GitHub Desktop.
using literal types in scala 2.13 to track the half-life of an exponential decay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Timestamp(epochMillis: Long) | |
case class Decay[H <: Double](scaledTime: Double, value: Double) { | |
def timestampDouble(implicit v: ValueOf[H]): Double = | |
scaledTime * v.value | |
def timestamp(implicit v: ValueOf[H]): Timestamp = | |
Timestamp(timestampDouble.toLong) | |
def combine(that: Decay[H]): Decay[H] = | |
if (scaledTime > that.scaledTime) that.combine(this) | |
else { | |
// we know scaledTime <= that.scaledTime | |
val decayThis = math.exp(scaledTime - that.scaledTime) * value | |
if (decayThis == 0.0) that | |
else Decay[H](that.scaledTime, that.value + decayThis) | |
} | |
} | |
object Decay { | |
def build[H <: Double: ValueOf, N: Numeric](time: Timestamp, n: N): Decay[H] = | |
Decay(time.epochMillis.toDouble / valueOf[H], implicitly[Numeric[N]].toDouble(n)) | |
implicit def monoidForDecay[H <: Double]: Monoid[Decay[H]] = | |
new Monoid[Decay[H]] { | |
val empty = Decay[H](Double.NegativeInfinity, 0.0) | |
def combine(l: Decay[H], r: Decay[H]): Decay[H] = l.combine(r) | |
} | |
} |
That works better (and makes more sense ;) Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
yeah, unfortunately, I posted before I ironed out usability.
Change
apply
todef build
because currently you are getting confused with the apply method. (also I wouldn't use the implicit conversion).