#arrow
Title
ł

Łukasz Gendek

02/06/2023, 12:47 PM
Hello, given the following code
Copy code
``````import arrow.core.Either
import arrow.core.continuations.Raise
import arrow.core.continuations.either

object DivisionByZero
data class IntegerParseError(val value: String)

context(Raise<IntegerParseError>)
fun parseIntegerCt(a: String) : Int = a.toIntOrNull() ?: raise(IntegerParseError(a))

context(Raise<DivisionByZero>)
fun divideIntegersCt(a: Int, b: Int): Int = if (b == 0)
raise(DivisionByZero)
else
a / b

context(Raise<IntegerParseError>, Raise<DivisionByZero>)
fun divideStrings(a: String, b: String): Int = divideIntegersCt(parseIntegerCt(a), parseIntegerCt(b))

fun parseInteger(a: String) : Either<IntegerParseError, Int> = either { parseIntegerCt(a) }

fun divideIntegers(a: Int, b: Int): Either<DivisionByZero, Int> = either {divideIntegersCt(a, b)}

fun divideStrings(a: String, b: String) : Either<IntegerParseError, Either<DivisionByZero, Int>> {
TODO()
//how to call divideStringsCt and return Either containing all possible cases
//could it be implemented it in a generic way?
}``````
I am not sure how to implement the divideStrings method, Could you help me?
s

simon.vergauwen

02/06/2023, 12:54 PM
Hey @Łukasz Gendek, You can simply call:
Copy code
``````context(Raise<IntegerParseError>, Raise<DivisionByZero>)
fun divideStrings(a: String, b: String): Int =``````
While providing the order in which you want the errors to be returned, int his case it should be inferable from the return type.
Copy code
``````fun divideStrings(a: String, b: String) : Either<IntegerParseError, Either<DivisionByZero, Int>> = either {
either { divideStrings(a, b) }
}``````
Are these signatures not conflicting though? 🤔
Copy code
``````context(Raise<IntegerParseError>, Raise<DivisionByZero>)
fun divideStrings(a: String, b: String): Int

fun divideStrings(a: String, b: String) : Either<IntegerParseError, Either<DivisionByZero, Int>>``````
Also not sure what you meant with:
Copy code
``// could it be implemented it in a generic way?``
If you were trying to build an example using the other
``Either``
functions you can do it the same as the other one but you'd be required calling
``bind``
.
Copy code
``````fun divideStrings(a: String, b: String) : Either<IntegerParseError, Either<DivisionByZero, Int>> = either {
either {
divideIntegers(
parseInteger(a).bind(),
parseInteger(b).bind()
).bind()
}
}``````
ł

Łukasz Gendek

02/06/2023, 3:59 PM
Thank you for your quick response. It is extremely useful for me.
Copy code
``````fun divideStrings(a: String, b: String) : Either<IntegerParseError, Either<DivisionByZero, Int>> = either {
either { divideStrings(a, b) }
}``````
By the generic implementation I meant the code below, but it unfortunately does not compile.
But it is the context receivers not the arrow to blame.
s

simon.vergauwen

02/06/2023, 4:14 PM
Ah, that is currently a bug in Kotlin compiler afaik
y

Youssef Shoaib [MOD]

02/07/2023, 7:48 PM
You can suppress that error BTW. I believe it is
``@Suppress("SUBTYPING_BETWEEN_CONTEXT_RECEIVERS")``
ł

Łukasz Gendek

02/08/2023, 9:58 AM
thank you, it helped with the subtyping error, but still cannot call the block function
image.png
s

simon.vergauwen

02/08/2023, 9:59 AM
I think you have to manually wire the context here 😞 Does this work?
Copy code
``````either outer@ {
either inner@ {
block(outer, inner)
}
}``````
It can be that you also have to add this workaround: Adding
``TypePlacedHolder<C>``
into the argument position of the lambda, or the call sites won't resolve correctly.
Copy code
``````@OptIn(ExperimentalContracts::class)
inline fun <A, B, C, R> with(a: A, b: B, c: C, block: context(A, B, C) (TypePlacedHolder<C>) -> R): R {
contract { callsInPlace(block, EXACTLY_ONCE) }
return block(a, b, c, TypePlacedHolder)
}

sealed interface TypePlacedHolder<out A> {
companion object : TypePlacedHolder<Nothing>
}``````
ł

Łukasz Gendek

02/08/2023, 10:04 AM
Copy code
``````@Suppress("SUBTYPING_BETWEEN_CONTEXT_RECEIVERS")
public fun <E1, E2, A> eitherC(block: context(Raise<E1>, Raise<E2>)() -> A): Either<E1, Either<E2, A>> = either outer@{
either inner@{
block(this@outer, this@inner)
}
}``````
it works, thank you
I've just updated the arrow library and I can see these shiny new colours (the 'raise' method). Very helpful and very nice.
🙂
16 Views