Kotlin - 推断两个泛型参数之一的类型
Posted
技术标签:
【中文标题】Kotlin - 推断两个泛型参数之一的类型【英文标题】:Kotlin - Infer type for one of two generic parameters 【发布时间】:2022-01-18 01:08:24 【问题描述】:我正在尝试创建一个具有两种泛型类型的函数:一种是具体化的,另一种是从其使用上下文派生的(因为它是一个扩展函数):
inline fun <reified E, A> Either<Throwable, A>.bypassLeft(transformation: Throwable.() -> A): Either<Throwable, A> =
when (this)
is Either.Left -> when (value)
is E -> value.transformation().right()
else -> this
else -> this
我们的想法是调用仅提及具体类型的函数,例如:
a.bypassLeft<NoResultException> ""
其中“a”是一个类型为 Either
但是编译器不让我放弃它,并要求我指定两种泛型类型,而不是从调用函数的对象中派生第二种。 这似乎是一件很合理的事情,但也许我错了......
这有可能实现吗?如果是这样,我做错了什么?
【问题讨论】:
不幸的是,据我所知,目前这是不可能的。我等待在这方面的语言改进,因为这个问题不时让我烦恼。如果有人告诉我我真的错了,我会很高兴。 【参考方案1】:目前不可能使用一个函数来赋予一个类型参数并让另一个类型参数被推断。如果您通过将实现更改为不使用接收器类型来键入 lambda 参数,则可以实现您想要的。
我在其中添加了一个额外的 impl,它显示了类型 args 也可以部分应用于类或其他周围范围。
import arrow.core.Either
import arrow.core.right
inline fun <reified E : Throwable, A> Either<Throwable, A>.bypassLeft(
transformation: (E) -> A //changed to regular arg not receiver
): Either<Throwable, A> =
when (this)
is Either.Left -> when (val v = value) //name locally for smart cast
is E -> transformation(v).right()
else -> this
else -> this
class Catch<A>(val f: () -> A) //alternative impl with partial type app
inline fun <reified E : Throwable> recover(
recover: (E) -> A
): Either<Throwable, A> =
Either.catch(f).fold(
if (it is E) Either.Right(recover(it))
else Either.Left(it)
,
Either.Right(it)
)
suspend fun main()
val x: Either<Throwable, Int> = Either.Left(***Error())
val recovered = x.bypassLeft
s: ***Error -> //here infers E
0 // here infers A
println(recovered) // Either.Right(0)
val notRecovered: Either<Throwable, Int> =
Catch
throw NumberFormatException()
1
.recover<***Error> 0
println(notRecovered) // Either.Left(java.lang.NumberFormatException)
【讨论】:
以上是关于Kotlin - 推断两个泛型参数之一的类型的主要内容,如果未能解决你的问题,请参考以下文章