Last active
January 15, 2019 09:55
-
-
Save loicdescotte/c4979248d2b2602cca2e25913490cb99 to your computer and use it in GitHub Desktop.
Compose errors (or nullables) and async functions in Scala, Kotlin, Typescript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import arrow.core.Either | |
import arrow.core.Either.Companion.left | |
import arrow.core.Either.Companion.right | |
import arrow.core.Option | |
import arrow.core.Some | |
import arrow.core.flatMap | |
import arrow.instances.either.monad.binding | |
import kotlinx.coroutines.async | |
import kotlinx.coroutines.delay | |
import kotlinx.coroutines.runBlocking | |
fun main(args: Array<String>) { | |
val total = giveInt2(giveInt(1)) | |
println("total: $total") | |
val totalWithNullables: Int? = giveNullableInt(1)?.let { giveNullableInt2(it) } | |
val totalWithOptions: Option<Int> = giveOptionInt(1).flatMap { giveOptionInt2(it) } | |
val totalWithEithers: Either<String, Int> = giveEitherStringInt(1).flatMap { giveEitherStringInt2(it) } | |
val totalWithLeftError: Either<String, Int> = giveEitherStringInt(1).flatMap { giveEitherStringInt3(it) } | |
//GlobalScope.launch { | |
//use runBlocking here to be able to see the output before the end of the program | |
runBlocking { | |
val totalWithEitherCoroutines: Either<String, Int> = giveEitherStringInt(1).flatMap { giveEitherStringInt2(it) } | |
val asyncResult1 = async { giveEitherStringIntCoroutine(1) } | |
val asyncResult2 = async { giveEitherStringIntCoroutine2(2) } | |
val asyncTotalWithEitherCoroutines: Either<String, Int> = | |
asyncResult1.await().flatMap { r1 -> asyncResult2.await().map { r2 -> r1 + r2 } } | |
//same example with bind syntax | |
val awaitedR1 = asyncResult1.await() | |
val awaitedR2 = asyncResult2.await() | |
val asyncTotalWithEitherCoroutines2: Either<String, Int> = | |
binding { | |
val r1 = awaitedR1.bind() | |
val r2 = awaitedR2.bind() | |
r1 + r2 | |
} | |
} | |
} | |
fun giveInt(x: Int): Int { | |
return x + 1 | |
} | |
fun giveInt2(x: Int): Int { | |
return x + 2 | |
} | |
fun giveNullableInt(x: Int): Int? { | |
return x + 1 | |
} | |
fun giveNullableInt2(x: Int): Int? { | |
return x + 2 | |
} | |
fun giveOptionInt(x: Int): Option<Int> { | |
return Some(x + 1) | |
} | |
fun giveOptionInt2(x: Int): Option<Int> { | |
return Some(x + 2) | |
} | |
fun giveEitherStringInt(x: Int): Either<String, Int> { | |
return right(x + 1) | |
} | |
fun giveEitherStringInt2(x: Int): Either<String, Int> { | |
return right(x + 2) | |
} | |
fun giveEitherStringInt3(x: Int): Either<String, Int> { | |
return left("unexpected error") | |
} | |
suspend fun giveEitherStringIntCoroutine(x: Int): Either<String, Int> { | |
delay(1000) | |
return right(x + 1) | |
} | |
suspend fun giveEitherStringIntCoroutine2(x: Int): Either<String, Int> { | |
delay(1000) | |
return right(x + 2) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.util._ | |
import scala.concurrent.Future | |
import io.github.hamsters.FutureEither | |
import io.github.hamsters.MonadTransformers._ | |
import scala.concurrent.ExecutionContext.Implicits.global | |
def giveInt(x: Int ): Int = x + 1 | |
def giveInt2(x: Int ): Int = x + 2 | |
def giveFuture(x: Int): Future[Int] = Future.successful(x + 1) | |
def giveFuture2(x: Int ): Future[Int] = Future.successful(x + 2) | |
def giveOption(x: Int ): Option[Int] = Some(x + 1) | |
def giveOption2(x: Int ): Option[Int] = Some(x + 2) | |
def giveEither(x: Int): Either[String, Int] = Right(x + 1) | |
def giveEither2(x: Int): Either[String, Int] = Right(x + 2) | |
def giveFutureEither(x: Int ): Future[Either[String, Int]] = Future.successful(Right(x + 1)) | |
def giveFutureEither2(x: Int ): Future[Either[String, Int]] = Future.successful(Right(x + 2)) | |
giveInt2(giveInt(1)) //4 | |
giveOption(1).flatMap(giveOption2) //Some(4) | |
//OR | |
for { | |
a <- giveOption(1) | |
b <- giveOption2(a) | |
} yield b // Some(4) | |
giveEither(1).flatMap(giveEither2) //Right(4) | |
for { | |
a <- giveFuture(1) | |
b <- giveFuture2(a) | |
} yield b // Future(4) | |
(for { | |
a <- FutureEither(giveFutureEither(1)) | |
b <- FutureEither(giveFutureEither2(a)) | |
} yield b).wrapped // Future(Right(4)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Option, some, none } from 'fp-ts/lib/Option' | |
import { Either, left, right } from 'fp-ts/lib/Either' | |
import { TaskEither, fromEither, tryCatch } from 'fp-ts/lib/TaskEither' | |
function giveInt(x: number ): number { | |
return x + 1 | |
} | |
function giveInt2(x: number ): number { | |
return x + 2 | |
} | |
async function giveIntAsync(x: number ): Promise<number> { | |
const result = await x +1 | |
return result | |
} | |
async function giveIntAsync2(x: number ): Promise<number> { | |
const result = await x +2 | |
return result | |
} | |
function giveOptionInt(x: number ): Option<number> { | |
return some(x + 1) | |
} | |
function giveOptionInt2(x: number ): Option<number> { | |
return some(x + 2) | |
} | |
function giveEitherStringInt(x: number ): Either<string, number> { | |
return right(x + 1) | |
} | |
function giveEitherStringInt2(x: number ): Either<string, number> { | |
return right(x + 2) | |
} | |
async function giveEitherStringIntAsync(x: number ): Promise<Either<string, number>> { | |
const either: Either<string, number> = right(x +1) | |
const result = await either | |
return result | |
} | |
//create TaskEither from promise | |
function giveTaskEitherStringInt(x: number): TaskEither<string, number> { | |
return tryCatch(() => giveIntAsync(x), reason => "oops " + reason) | |
} | |
//create TaskEither from Either | |
function giveTaskEitherStringIn2t(x: number ): TaskEither<string, number> { | |
return fromEither(giveEitherStringInt2(x)) | |
} | |
console.log(giveInt2(giveInt(1))) //4 | |
console.log(giveOptionInt(1).chain(giveOptionInt2)) //some(4) | |
console.log(giveEitherStringInt(1).chain(giveEitherStringInt2)) //right(4) | |
giveIntAsync(1).then(giveIntAsync2).then(console.log) //4 | |
giveTaskEitherStringInt(1).chain(giveTaskEitherStringIn2t).run().then(console.log) //right(4) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment