I am trying to create a infix notation as a extension function of (Int) -> Int function which is used to nest a function to another.
For example:
class Entry {
companion object {
private fun f(x: Int) = x * 2
private fun g(x: Int) = x 2
private infix fun ((Int) -> Int).nest(inner: (Int) -> Int) = { x: Int -> this(inner(x)) }
@JvmStatic
fun main(args: Array<String>) {
val func = ::f nest ::g
println(func(10))
}
}
}
This code works fine, it created a infix notation nest as a extension function to (Int) -> Int function. It requires another (Int) -> Int function and nest them together.
val func = ::f nest ::g is equals to val fun func(x:Int) = f(g(x))
func(10) is equals to (10 2) * 2.
But I encountered a problem when I tried to extend this extension notate function to Number interface (for supporting all kinds of numbers).
For example:
class Entry {
companion object {
private fun f(x: Int) = x * 2
private fun g(x: Int) = x 2
private infix fun ((Number) -> Number).nest(inner: (Number) -> Number) = { x: Number -> this(inner(x)) }
// only the infix fun declaration changed ^
@JvmStatic
fun main(args: Array<String>) {
val func = ::f nest ::g
println(func(10))
}
}
}
The kotlin compiler throws an error.
Kotlin: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
private final infix fun ((Number) -> Number).nest(inner: (Number) -> Number): (Number) -> Number defined in ...(path of class Entry)
I am wondering why Int extends from Number, but (Int) -> Int doesn't match to (Number) -> Number.
If I want to extend this notation function to all functions that ask for a number and returns a number (for example, (Long) -> Long (Float) -> Double etc.), what should I do?
CodePudding user response:
Note that a (Int) -> Int is not a kind of (Number) -> Number. Namely, you can give any Number to a (Number) -> Number, but you can only pass Ints to a (Int) -> Int.
By your logic, I would be able to nest a (Int) -> Int with a (Double) -> Double, since (Double) -> Double is also a (Number) -> Number (by your logic), but that certainly doesn't make sense, does it? You can't pass a Double to a (Int) -> Int.
Your nest function could be written more generally with generics:
infix fun <T, U, V> ((U) -> V).nest(inner: (T) -> U) = { x: T -> this(inner(x)) }
It is possible to nest any (U) -> V with (T) -> U, producing a (T) -> V.
