我正在嘗試創建一個具有兩種泛型型別的函式:一種是具體化的,另一種是從其使用背景關系派生的(因為它是一個擴展函式):
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<Throwable,String>的物件
但是編譯器并沒有讓我放棄它,并要求我指定兩種泛型型別,而不是從呼叫函式的物件中派生出第二種型別。這似乎是一件很合理的事情,但也許我錯了......
這有可能實作嗎?如果是這樣,我做錯了什么?
uj5u.com熱心網友回復:
目前不可能使用一個函式來歸因于單個型別引數并保留另一個型別引數。如果通過將實作更改為不使用接收器型別來鍵入 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(StackOverflowError())
val recovered = x.bypassLeft {
s: StackOverflowError -> //here infers E
0 // here infers A
}
println(recovered) // Either.Right(0)
val notRecovered: Either<Throwable, Int> =
Catch {
throw NumberFormatException()
1
}.recover<StackOverflowError> { 0 }
println(notRecovered) // Either.Left(java.lang.NumberFormatException)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/382080.html
標籤:科特林 泛型 函数式编程 箭头-kt kotlin-reified-type-parameters
