than_
03/31/2023, 12:02 PMEither::getOrElse
. The behaviour I like there is being able to affect the return type in the recover block.
val a: Either<Something, Int>
val r1: Int = a.getOrElse{ 0 }
val r2: Int = a.getOrElse { throw ... }
val r3: Int = a.getOrElse { raise(...) }
val r4: Int? = a.getOrElse { null }
While playing around I came up with:
inline fun <ERR, A, B : BB, BB> A.toB(
transform: Raise<ERR>.(A) -> B,
recover: (ERR) -> BB,
) = fold({ transform(this@toB) }, { recover(it) }, ::identity)
So now I can do (just as example):
val r1: Long? = "abc".toB({
it.toLongOrNull() ?: raise(Unit)
}) {
null
}
The behaviour is correct but it'd be nice to wrap it in a function String::toLongOrElse
The issue is how would you implement that?
inline fun <T: Long?> String.toLongOrElse(recover: () -> T): T =
this.toB({
it.toLongOrNull() ?: raise(Unit)
}) {
recover()
}
This doesn't really work since the transform requires to return T
but returns`Long`simon.vergauwen
03/31/2023, 12:05 PMtoB
for this to work 🤔simon.vergauwen
03/31/2023, 12:09 PMT : Long?
🤔 It can only be Long?
so no generic is needed.simon.vergauwen
03/31/2023, 12:09 PMrecover
returns a nullable but non-null if there is a non-null Long
returned from recover
? 🤔than_
03/31/2023, 12:10 PMtoB
when used on it's own works well. It infers common parent from return types of transform and recover. The issue is wrapping it in a function for a concrete type. I'm able to implement Either::getOrElse
with it without issues:
fun <ERR, B : BB, BB> Either<ERR, B>.getOrElse(recover: (ERR) -> BB) = toB({
it.fold(
ifLeft = { raise(it) },
ifRight = ::identity
)
}) {
recover(it)
}
than_
03/31/2023, 12:10 PMthan_
03/31/2023, 12:18 PMtoB
and even when implementing the getOrElse
the inference is possible, (at least in some cases).simon.vergauwen
03/31/2023, 12:34 PMT : Long?
but not that Long
is intersects with T
in a generic environment, but when doing it in a "concrete" environment it can infer the upper bound correctly.than_
03/31/2023, 12:54 PMLong?
extends Long
. Am I not correct? You can assign Long
to Long?
but not vice versa so in that case compiler can infer the relationship.simon.vergauwen
03/31/2023, 1:00 PMLong
extends Long?
but Long
is not perse T : Long?
since T
can be a different subtypesimon.vergauwen
03/31/2023, 1:00 PMinline fun <T: Long?> String.toLongOrElse(recover: () -> T): Long? =
this.toB({
it.toLongOrNull() ?: raise(Unit)
}) {
recover()
}
than_
04/01/2023, 12:29 PMsimon.vergauwen
04/01/2023, 5:50 PM