Created
          August 6, 2025 13:23 
        
      - 
      
- 
        Save komu/c2f249d86a24a5ea07a20a4099580bff to your computer and use it in GitHub Desktop. 
  
    
      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
    
  
  
    
  | 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