Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin generic number Union?

I want to implement a cumulative sum method for List, such a function should accept List<Int>, List<Float>, etc.

I could go as far as to say that it should accept List<anything that implements add>

But I see no way of specifying this in the official documentation.

I have tried using the type Number but it apparently does not work.

How should I go about making a generic extension function that accepts any type implementing a particular method like add?

like image 410
Rares Dima Avatar asked Oct 19 '25 04:10

Rares Dima


1 Answers

Why you can't add numbers

Numbers only have the following methods:

  • public abstract fun toDouble(): Double
  • public abstract fun toFloat(): Float
  • public abstract fun toLong(): Long
  • public abstract fun toInt(): Int
  • public abstract fun toChar(): Char
  • public abstract fun toShort(): Short
  • public abstract fun toByte(): Byte

There is no add, so you can't add them together

Workarounds

  • You can use the Iterable methods, which should be available on lists
  • You can wrap the Numbers, and have the wrappers supply an add method
  • You could use reflection to do this, but it might not be the best way

Hacky casting workaround

typealias Adder<T> = (T)->T

fun <T: Number> T.toAdder(): Adder<T> {
    return when(this) {
        is Long -> {{it -> (this as Long + it as Long) as T}}
        is Int -> {{it -> (this as Int + it as Int) as T}}
        is Double -> {{it -> (this as Double + it as Double) as T}}
        else -> throw AssertionError()
    }
}

fun <T: Number> List<T>.mySum(zero: T): T {
    return map { it.toAdder() }.fold(zero) { acc, func -> func(acc)  }
}

fun main(args: Array<String>) {
    val total = listOf(1,2,4).mySum(0)
}

This works, but it uses a lot of casting, and should be avoided

like image 60
jrtapsell Avatar answered Oct 22 '25 03:10

jrtapsell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!