Skip to content

Instantly share code, notes, and snippets.

@komu
Created August 6, 2025 13:23
Show Gist options
  • Save komu/c2f249d86a24a5ea07a20a4099580bff to your computer and use it in GitHub Desktop.
Save komu/c2f249d86a24a5ea07a20a4099580bff to your computer and use it in GitHub Desktop.
import kotlin.time.Duration
import kotlin.time.Instant
import kotlin.time.times
// First define some type classes
interface Plus<L, R, T> {
fun plus(x: L, y: R): T
}
interface Minus<L, R, T> {
fun minus(x: L, y: R): T
}
interface Multiply<L, R, T> {
fun multiply(x: L, y: R): T
}
// Define operators that can be used when an instance of the type class is in scope
context(plus: Plus<L, R, T>)
operator fun <L, R, T> L.plus(rhs: R): T = plus.plus(this, rhs)
context(plus: Minus<L, R, T>)
operator fun <L, R, T> L.minus(rhs: R): T = plus.minus(this, rhs)
context(multiply: Multiply<L, R, T>)
operator fun <L, R, T> L.times(rhs: R): T = multiply.multiply(this, rhs)
// Define some default instances
object DoubleMath : Plus<Double, Double, Double>, Minus<Double, Double, Double>, Multiply<Double, Double, Double> {
override fun plus(x: Double, y: Double) = x + y
override fun minus(x: Double, y: Double) = x - y
override fun multiply(x: Double, y: Double) = x * y
}
object InstantMath : Plus<Instant, Duration, Instant>, Minus<Instant, Instant, Duration>, Multiply<Double, Duration, Duration> {
override fun plus(x: Instant, y: Duration) = x + y
override fun minus(x: Instant, y: Instant) = x - y
override fun multiply(x: Double, y: Duration) = x * y
}
// A convenience function to run code with all our default instances
inline fun <T> withDefaultInstances(callback: context(InstantMath, DoubleMath) () -> T): T =
context(DoubleMath, InstantMath) {
callback()
}
// A call that works for any type with given type classes
context(_: Plus<T, R, T>, _: Minus<T, T, R>, _: Multiply<Double, R, R>)
fun <T, R> lerp(a: T, b: T, t: Double): T =
a + t * (b - a)
)
// A function that leverages our type classes
fun foo(startTime: Instant, endTime: Instant) = withDefaultInstances {
val a = lerp(0.4, 1.4, 0.2)
val b = lerp(startTime, endTime, 0.4)
println("a: $a, b: $b")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment