Kotlin 中的通用 lambda 或函数值类型

dev*_*ull 4 generics types functional-programming kotlin

给定一个函数

fun <T> to5(x: T): Int = 5
Run Code Online (Sandbox Code Playgroud)

是否可以funVal像这样将其分配给变量(值)?

val funVal: (T) -> Int = ::to5
Run Code Online (Sandbox Code Playgroud)

没有

未解决的参考:T

错误 ?

换句话说,是否可以以某种方式告诉 KotlinTfunVal类型声明中是一个类型参数?

例如这样:

val <T> funVal: (T) -> Int = ::to5

val funVal<T>: (T) -> Int = ::to5

val funVal: <T> (T) -> Int = ::to5

val funVal: ((T) -> Int) <T> = ::to5
Run Code Online (Sandbox Code Playgroud)

使用案例

我的用例是使用泛型柯里化。从概念上讲:

    fun pairStrWithStr(s: String): (String) -> Pair<String, String> = {
        Pair(s, it)
    }

    val pairStrWithAbc: (String) -> Pair<String, String> = pairStrWithStr("abc")

    pairStrWithAbc("xyz") // (abc, xyz)
Run Code Online (Sandbox Code Playgroud)

使第二个参数变得通用:

fun <T> pairStrWithAny(s: String): (T) -> Pair<String, T> = {
    Pair(s, it)
}

// Compilation ERROR: Unresolved reference: T
val pairAnyWithAbc: (T) -> Pair<String, T> = pairStrWithAny("abc")
Run Code Online (Sandbox Code Playgroud)

当然我可以提供Any以下类型:

val pairAnyWithAbc: (Any) -> Pair<String, Any> = pairStrWithAny("abc")
Run Code Online (Sandbox Code Playgroud)

但后来我丢失了类型信息:

pairAnyWithAbc(5) // Pair<String, Any>
Run Code Online (Sandbox Code Playgroud)

我能想到的解决方案是:

包装在通用乐趣中(基本上不是真正的柯里化或高阶函数使用)

 fun <T> pairAnyWithAbc(t: T) {
        return pairAnyWithAbc(t)
 }
Run Code Online (Sandbox Code Playgroud)

为每种类型创建函数(不使用我想要的泛型)

val pairStrWithAbc: (String) -> Pair<String, String> = pairStrWithAny("abc")

val pairIntWithAbc: (Int) -> Pair<String, Int> = pairStrWithAny("abc")
Run Code Online (Sandbox Code Playgroud)

zsm*_*b13 5

在 Kotlin 中,只有类和函数可以具有泛型类型参数。如果您确实需要一个属性具有泛型类型,则它必须属于可以提供该泛型类型的类实例,如下所示:

class Foo<T> {
    val funVal: (T) -> Int = ::to5
}
Run Code Online (Sandbox Code Playgroud)

这里有更多关于此问题的讨论,我只是不能将其标记为重复,因为该问题没有公认的答案。