Sam Pengilly
12/13/2022, 11:57 PMEffect
and Eval
. At first glance I see that Eval isn’t really an extension of suspend () -> A
but instead seems to have the purpose of collapsing potentially large callstack operations. Effect seems to provide functions like attempt
and fold
but seems a bit more like a wrapper around suspend () -> A
. Is it there to provide an extra layer of “semantics”, such as making it clear that a function returns a side-effecting operation versus just a suspending one? Should Effect
be used as a return type over suspend () -> A
? or are there use-cases for both?simon.vergauwen
12/14/2022, 7:31 AMEffect
is not really the interesting part, but rather EffectScope
or it's new named alternative Raise
.
Which allow you to bring the powers of typed errors, which is kind-of unrelated to IO
. You can see Effect<E, A>
as EitherT[IO, E, A]
, but without transformers or nesting of monads.simon.vergauwen
12/14/2022, 7:33 AMsuspend fun example(): Either<E, A>
where either { }
DSL works through EffectScope<E>
.simon.vergauwen
12/14/2022, 7:33 AMEffect
will be a simple typealias
to suspend Raise<E>.() -> A
in 2.x.x and 1.2.x.simon.vergauwen
12/14/2022, 7:35 AMEval
is discussed in Grokking Functional Programming, but it's quite useless in Kotlin and will probably be marked for deprecation towards 2.x.xsimon.vergauwen
12/14/2022, 7:35 AMIO
Sam Pengilly
12/14/2022, 8:04 AMSam Pengilly
12/14/2022, 8:06 AMsuspend () -> A
or suspend () -> Either<E, A>
? It's functionally equivalent but provides some additional conveniences in terms of the EffectScope DSL and other functions correct?Sam Pengilly
12/14/2022, 8:08 AMSam Pengilly
12/14/2022, 8:10 AMsimon.vergauwen
12/14/2022, 9:02 AMsuspend () -> A
from a function, but rather use suspend fun name(): A
. You rarely have to work with a suspend () -> A
value. You can think of it as marking a function with the io
capabilities, and allowing you to use invoke
instead of flatMap
for composing them.
Similarly you can then simply use Either
in the return type whenever needed.Sam Pengilly
12/14/2022, 9:04 AMsimon.vergauwen
12/14/2022, 9:04 AMEval
is used for stack-safety on the JVM, but since recently Kotlin offers other solutions for that. https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-deep-recursive-function/
But you can use tailrec
in combination with suspend fun
.simon.vergauwen
12/14/2022, 9:05 AMIO
monad, but you get used to it very quickly. It maps 1-on-1 to each other, but it just looks a bit different 😄Jorge Bo
02/15/2023, 4:16 PMsimon.vergauwen
02/15/2023, 4:18 PMEffect<E, A>
describes a function that results in an typed error E
, and exception Throwable
or a value A
.
In 1.2.x backport for 2.x.x it's very clear in the type, since it will now just be typealias Effect<E, A> = suspend Raise<E>.() -> A
.Jorge Bo
02/15/2023, 4:25 PMsimon.vergauwen
02/15/2023, 4:30 PMEither
is not incorrect as long as you write suspend fun program(): Either<E, A>
if you want to store it as val
or regular fun
then you'll want Effect<E, A>
.
Raise<E>
is the interesting bit though, as you can see in the typealias
. Instead of using effect { }
you'll also be able to to write suspend fun Raise<E>.program(): A
or with context receivers context(Raise<E>) suspend fun program(): A
.
I am working on new documentation for this. All of this is available in 1.1.6-alpha.27
or in the 1.2.0
we'll release in next weeks.simon.vergauwen
02/15/2023, 4:31 PMJorge Bo
02/15/2023, 5:00 PMclass FreeSideEffectRepositoryImpl : FreeSideEffectRepository {
override suspend fun storeEffect(reservation: Reservation): Effect<Unit, Unit> = effect {
//this is executed when evaluating to* methods
//eg.: FreeSideEffectRepositoryImpl.storeEffect(Reservation()).toEither()
throw IllegalArgumentException("error in effect")
}
override suspend fun storeEither(reservation: Reservation): Either<Unit, Unit> = either {
//this is executed as soon as FreeSideEffectRepositoryImpl.storeEither(Reservation()) is executed
throw IllegalArgumentException("error in either")
}
}
simon.vergauwen
02/15/2023, 5:19 PMsuspend
from suspend fun storeEffect(reservation: Reservation): Effect<Unit, Unit>
since effect { }
already gives you the power of suspend
lazily inside.Jorge Bo
02/15/2023, 9:52 PM