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 AMIOSam 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