Просто немного поигрался с этим и поделился некоторыми мыслями, в основном отвечая на последний вопрос: «Как мне написать функцию foo
, чтобы foo()(1)
скомпилировался, где bar
- универсальный тип?»:
Простой обходной путь, но затем вы отказываетесь от функции более высокого порядка (или вам нужно обернуть ее), чтобы иметь промежуточный объект на месте, например:
object FooOp {
operator fun <T> invoke(t : T) = t
}
с foo
-метод, подобный следующему:
fun foo() = FooOp
Конечно, это не совсем то же самое, поскольку вы в основном работаете с первой универсальной функцией.По сути, это почти то же самое, что просто иметь функцию 1, которая возвращает желаемый тип, и поэтому она также может выводить тип снова.
Альтернативой вашей проблеме может быть следующее.Просто добавьте еще одну функцию, которая на самом деле указывает тип:
fun <T> foo() = fun(bar: T): T = bar
@JvmName("fooInt")
fun foo() = fun(bar : Int) = bar
Следующие два затем будут успешными:
val t: Int = foo()(1)
val t2: String = foo<String>()("...")
, но ... (помимо потенциально требующих большого количества перегрузок) это не такМожно определить другую функцию, подобную следующей:
@JvmName("fooString")
fun foo() = fun(bar : String) = bar
Если вы определите эту функцию, она выдаст вам ошибку, подобную следующей:
Conflicting overloads: @JvmName public final fun foo(): (Int) -> Int defined in XXX, @JvmName public final fun foo(): (String) -> String defined in XXX
Но, возможно, вы сможетепостроить что-то с этим?
В противном случае у меня нет ответа на вопрос, почему оно выведено, а почему нет.