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 Int
s 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
.