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?
Note that a
(Int) -> Intis not a kind of(Number) -> Number. Namely, you can give anyNumberto a(Number) -> Number, but you can only passInts to a(Int) -> Int.By your logic, I would be able to
nesta(Int) -> Intwith a(Double) -> Double, since(Double) -> Doubleis also a(Number) -> Number(by your logic), but that certainly doesn't make sense, does it? You can't pass aDoubleto a(Int) -> Int.Your
nestfunction could be written more generally with generics:It is possible to nest any
(U) -> Vwith(T) -> U, producing a(T) -> V.