Ulrich Schuster
02/15/2024, 10:36 AMEither.catch{..} and the raise DSL? I'm having the following problem:
either {
zipOrAccumulate(
{ ensureNotNull(<some function>) { MyErrorType1 },
{ ensureNotNull(<some other function>) { MyErrorType2 },
{ Either.catch { MyEnum.valueOf(someString) }.mapLeft { MyErrorType3 }
) { a, b, c -> MyType(a, b, c)
}
The Either.catch block does not type check, because the result is not compatible with the raise DSL. What is the idiomatic way to do it?dave08
02/15/2024, 10:41 AMEither.)?Ulrich Schuster
02/15/2024, 10:46 AMUlrich Schuster
02/15/2024, 10:48 AMeither {
zipOrAccumulate(
{ ensureNotNull(<some function>) { MyErrorType1 },
{ ensureNotNull(<some other function>) { MyErrorType2 },
{ catch( { MyEnum.valueOf(someString) } ) { raise(MyErrorType3) } }
) { a, b, c -> MyType(a, b, c)
}simon.vergauwen
02/15/2024, 3:46 PMRaise<E> then you can call Either.bind on Either<E, A>.
So I am assuming in this case that MyErrorType1, MyErrorType2 and MyErrorType3 have a common parent. I am going to define one MyError so:
sealed interface MyError // (or sealed class)
object MyErrorType1 : MyError
object MyErrorType2 : MyError
object MyErrorType3 : MyError
And then we need to apply bind within your previous snippet so:
either/*<NonEmptyList<MyError>, MyType>*/ { /* Raise<E>.() -> */
zipOrAccumulate(
{ ensureNotNull(<some function>) { MyErrorType1 },
{ ensureNotNull(<some other function>) { MyErrorType2 },
{ Either.catch { MyEnum.valueOf(someString) }.mapLeft { MyErrorType3 }.bind() }
) { a, b, c -> MyType(a, b, c) }
}simon.vergauwen
02/15/2024, 3:48 PMRaise, and Either are always interchangeable.
To go from Either<E, A> to A in Raise you need to make sure that the generic parameter of Raise matches the error type of Either in this case E. (common parent).
To go from Raise<E> to A you use the either { } builder, or DSL. Which you're also already using here.
So if you work with Either using either { }, then you're in fact already using Raise all the time ☺️simon.vergauwen
02/15/2024, 3:51 PMEither as a "wrapper type", and Raise<E> relies on DSLs and never requires wrapping values.
You can also see this all over the Kotlin ecosystem:
• Option is a wrapper, ? is unwrapped.
• Future (wrapper), and as suspend (unwrapped)
However, there are many people that prefer using Either over Raise (which kind-of implies context receivers to all benefits from it). At least, that is our prediction/expectation.Ulrich Schuster
02/15/2024, 3:52 PMsimon.vergauwen
02/15/2024, 4:18 PM