11

It would be a basic question, but I couldn't figure out a solution. I need to initialize a constant out of the right-side value of below either type.

val test: Either<String, Int> = 1.right()

I tried something like below but it shrinks the scope of the constant.

when(test) {
        is Either.Right -> {val get:Int = test.b}
        is Either.Left -> println(test.a)
    }

I want that get to be scoped outside of when statement. Is there any way to do it or Arrow Either is not made for this purpose?

3
  • And what should get be if value is left? null? Use when as a statement. Commented May 12, 2020 at 20:45
  • @Nicolas edited my question. If I use when as expression then again I get into the same problem whether get gonnabe Int or String then kotlin choose any as type Commented May 12, 2020 at 20:47
  • 1
    @Vencat in FP Either denotes code branching where both branches are possible. The only way to get rid of the left branch is to provide a value of the same type than the right one in that case. Look at LordRaydenMk's answer for this. Still that is not a convenient way to work. What you do in FP instead is keep it as an Either and compose the program operations on top, using combinators like map, flatMap etc as LordRaydenMk shows below. Those operate over the happy case (Right). Then at some point you plug an error handling strategy by calling fold() and handling errors on Left side. Commented May 13, 2020 at 8:58

1 Answer 1

15

The important question is: what should happen if the Either is Left. In this example it is created close to where it's used, so it is obvious to you as a developer. But to the compiler what is inside the Either can be either an Int or a String.

You can extract the value using for example fold:

val x = test.fold({ 0 }, {it}) // provide 0 as default in case the Either was a `Left`
// x = 1

another option is getOrElse

val test = 1.right()
val x = test.getOrElse { 42 } // again, default in case it was a `Left`
// x = 42

You can also work with it without unwrapping it:

val test = 1.right()
val testPlus10 = test.map { it + 10 } // adds 10 to `test` if it is `Right`, does nothing otherwise
val x = testPlus10.getOrElse { 0 } // unwrap by providing a default value
// x = 11

For more example check the official docs.

Recommended reading: How do I get the value out of my Monad

Sign up to request clarification or add additional context in comments.

1 Comment

This is a very accurate answer. The recommended approach would be the last one, where you keep it as an Either and stack operations on top of it, plugging a fold at some point for processing both sides. Some additional info about error handling using Either arrow-kt.io/docs/0.10/patterns/error_handling/#either

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.