Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For comprehensions with kotlin and arrow-kt library

I use arrow-kt library and I'm trying to employ Either and IO within the same for comprehension.

Say I have the next piece of code:

IO.monad().binding {
    val ans: Either<Error, Data> = someFunctionThatReturnsEitherWrappedInIO().bind()
}

Now, I'd like to use binding on the ans:

val data: Data = ans.bind() // My intent

Is it possible to do It whithin the scope of the first piece of code?

Currently I'm trying to nest an Either binding within the scope of the IO binding, but I'm not sure this is a good practice:

IO.monad().binding {
    val ans: Either<Error, Data> = someFunctionThatReturnsEitherWrappedInIO().bind()
    val ansB: Either<Error, OtherData> = someOtherFunctionThatReturnsEitherWrappedInIO().bind()

    val newData: Either<Any, NewData> = Either.monad<Any>().binding {
        val data: Data = ans.bind()
        val otherData: OtherData = ansB.bind()
        NewData(data.a, otherData.lala)
    }.fix()
}
like image 321
MaxG Avatar asked Dec 12 '18 15:12

MaxG


Video Answer


1 Answers

Background

First I should mention that Monads don't compose, that's why you need a Monad transformer, in your case EitherT is the guy that can help you.

Example

object Error

fun one() = IO { Right(1) }
fun two() = IO { Right("2") }
fun toInt(str: String) = IO { Try { str.toInt() }.toEither { Error } }

val result: IO<Either<Error, Int>> =
    EitherT.monad<ForIO, Error>(IO.monad()).binding {
        val oneInt = EitherT(one()).bind()
        val twoString = EitherT(two()).bind()
        val twoInt = EitherT(toInt(twoString)).bind()
        oneInt + twoInt
    }.value().fix()

println(result.unsafeRunSync()) // Just for demonstration, don't do this ever

Right(b=3)

like image 94
Omar Mainegra Avatar answered Nov 20 '22 12:11

Omar Mainegra