xenomachina
07/03/2018, 6:15 PMval foo = myEither.getOrElse { return false }
but Kotlin won't allow this because the lambda to getOrElse
is crossinline
. Why is it declared crossinline
?Andreas Sinz
07/03/2018, 6:42 PMxenomachina
07/03/2018, 6:43 PMxenomachina
07/03/2018, 6:46 PMval foo = myEither.getOrElse { return false }
val bar = someValidated.getOrElse { return false }
val baz = Baz(name = foo.name, size = bar.count, color = myTry.getOrElse { return false })
// computations that use foo, bar and/or baz go here
return true
xenomachina
07/03/2018, 6:48 PMpakoito
07/03/2018, 6:51 PMpakoito
07/03/2018, 6:51 PMEither.applicative().map(myEither, someValidated.toEither(), myTry.toEither())
{ foo, bar, baz ->
// computations and sheeeet
}.fold({ false }, { true })
pakoito
07/03/2018, 6:54 PMpakoito
07/03/2018, 6:55 PMpakoito
07/03/2018, 6:56 PMEither.applicative().map(myEither, someValidated.toEither(), myTry.toEither())
{ foo, bar, baz -> Buzz(foo, bar, baz) }
.flatMap { buzz ->
somethingThatMayFail(buzz).toEither()
}
.fold({ false }, { true })
xenomachina
07/03/2018, 6:58 PMxenomachina
07/03/2018, 7:02 PMEither.applicative()
? Kotlin's just telling me "unresolved reference", and IntelliJ can't figure out where to import it from.pakoito
07/03/2018, 7:02 PMpakoito
07/03/2018, 8:43 PMxenomachina
07/03/2018, 8:43 PMxenomachina
07/03/2018, 8:46 PMval foo = myEither.getOrElse { return false }
val bar = someThingThatReturnsAValidated(foo).getOrElse { return false }
val baz = Baz(name = foo.name, size = bar.count, color = myTry.getOrElse { return false })
// computations that use foo, bar and/or baz go here
return true
xenomachina
07/03/2018, 8:50 PMxenomachina
07/03/2018, 8:51 PMpakoito
07/03/2018, 9:20 PMpakoito
07/03/2018, 9:22 PMmyEither.flatMap { foo ->
Either.applicative()
.map(someThingThatReturnsAValidated(foo).toEither(),
myTry.toEither()) {
Buzz(foo, bar, baz)
}
}.flatMap { buzz ->
somethingThatMayFail(buzz).toEither()
}
.fold({ false }, { true })
pakoito
07/03/2018, 9:24 PMpakoito
07/03/2018, 9:26 PMEither.monadError().bindingCatch {
val foo = myEither.bind()
val bar = someThingThatReturnsAValidated(foo).toEither().bind()
val baz = myTry.toEither().bind()
val buzz = Buzz(foo, bar, baz)
somethingThatMayFail(buzz).toEither()
.fold({ false }, { true })
}
xenomachina
07/03/2018, 10:31 PMpakoito
07/03/2018, 10:34 PMpakoito
07/03/2018, 10:34 PMpakoito
07/03/2018, 10:35 PMxenomachina
07/03/2018, 10:43 PMpakoito
07/03/2018, 10:45 PMpakoito
07/03/2018, 10:45 PMEither.monadError<Throwable>()
pakoito
07/03/2018, 10:46 PMpakoito
07/03/2018, 10:46 PMTry
expects so it’s the most general inferencexenomachina
07/03/2018, 10:52 PMpakoito
07/03/2018, 11:00 PMpakoito
07/03/2018, 11:01 PMsealed class Wrong {
data class FromEither(???): Wrong()
data class FromEither(???): Wrong()
data class FromTry(t: Throwable): Wrong()
}
xenomachina
07/03/2018, 11:02 PMpakoito
07/03/2018, 11:16 PMbinding
in .monad()
, but you have to do something about that Try
. Maybe mapLeft
after converting to Either
pakoito
07/03/2018, 11:17 PMxenomachina
07/03/2018, 11:20 PMmapLeft { false }
on each of them, since I'm using false for error in any case.xenomachina
07/03/2018, 11:27 PMpakoito
07/03/2018, 11:53 PMpakoito
07/03/2018, 11:53 PMpakoito
07/03/2018, 11:53 PMpakoito
07/03/2018, 11:54 PMpakoito
07/03/2018, 11:54 PMpakoito
07/03/2018, 11:54 PMxenomachina
07/03/2018, 11:56 PMxenomachina
07/03/2018, 11:57 PMpakoito
07/03/2018, 11:59 PMpakoito
07/03/2018, 11:59 PMpakoito
07/04/2018, 12:01 AMTry
is a value and is composable, which means it’s possible to store and modify itxenomachina
07/04/2018, 12:03 AMpakoito
07/04/2018, 12:07 AMxenomachina
07/04/2018, 12:08 AMpakoito
07/04/2018, 12:14 AMxenomachina
07/04/2018, 12:15 AMpakoito
07/04/2018, 12:16 AMpakoito
07/04/2018, 12:16 AMpakoito
07/04/2018, 12:16 AMxenomachina
07/04/2018, 12:21 AMpakoito
07/04/2018, 12:24 AMpakoito
07/04/2018, 12:24 AMpakoito
07/04/2018, 12:24 AMpakoito
07/04/2018, 12:26 AMsealed class CatchAll<T> {
data class Original<T>(val value: T): CatchAll<T>()
object UnknownError: CatchAll<Nothing>()
}
xenomachina
07/04/2018, 12:26 AMpakoito
07/04/2018, 12:26 AMpakoito
07/04/2018, 12:26 AMpakoito
07/04/2018, 12:27 AMpakoito
07/04/2018, 12:27 AMxenomachina
07/04/2018, 12:31 AMinline fun <reified X : Throwable, R> catchEither(block: () -> R) : Either<X, R> =
try {
Either.Right(block())
} catch(exc: X) {
Either.Left(exc)
}
}
Wouldn't work if there's more than one kind of exception, though.pakoito
07/04/2018, 12:34 AMpakoito
07/04/2018, 12:36 AMTry { /* javacode() */ }
.recover { if (it is X) it else throw it }.toEither()
pakoito
07/04/2018, 12:36 AMxenomachina
07/04/2018, 12:39 AMThrowable
, and not the specific exception typepakoito
07/04/2018, 12:40 AMpakoito
07/04/2018, 12:41 AMxenomachina
07/04/2018, 12:44 AMpakoito
07/04/2018, 12:44 AMpakoito
07/04/2018, 12:44 AMpakoito
07/04/2018, 12:44 AMpakoito
07/04/2018, 12:45 AMTry { /* javacode() */ }
.toEither().mapLeft { if (it is X) it else throw it }
xenomachina
07/04/2018, 12:45 AMxenomachina
07/04/2018, 12:48 AMcatchEither<X> { /* javacode() */ }
is still a lot shorter...pakoito
07/04/2018, 12:49 AMinline fun <reified X : Throwable, R> catchEither(block: () -> R) : Either<X, R> =
Try { block() }
.toEither().mapLeft { if (it is X) it else throw it }
xenomachina
07/04/2018, 12:50 AMpakoito
07/04/2018, 12:51 AMpakoito
07/04/2018, 12:52 AMcatchEither
with the library because it’s specific to your use case (and it’s unsafe), but catchEither
definitely looks like something I’d have in my app, or tool, or backendxenomachina
07/04/2018, 12:56 AMxenomachina
07/04/2018, 12:58 AMpakoito
07/04/2018, 12:58 AMxenomachina
07/04/2018, 12:58 AM