raulraja
08/22/2022, 12:17 PMEffectScope
and the operation shift
to something else. 99% of the time shift is used for error propagation or short-circuiting.
We were wondering which one of the following you prefer:
1️⃣ Shift
context(Shift<Error>)
suspend fun example(): Int = shift(Error)
2️⃣ Raise
context(Raise<Error>)
suspend fun example(): Int = raise(Error)
3️⃣ CanFail
context(CanFail<Error>)
suspend fun example(): Int = fail(Error)
For more context on this see https://github.com/arrow-kt/arrow/pull/2797#issuecomment-1222239640
If you are interested in helping us decide please vote with one of those numbers or feel free to propose a new one or any question as thread comments to this post. Thanks!Sam
08/22/2022, 12:26 PMEither
doesn’t specify that left
means failure, I think it could be confusing for shift
to be replaced with something that specifically implies failure 🤔. For me, shift
is still the best because it conveys the sense of switching from a right-biased path to a left, without implying anything about the semantics.Stylianos Gakis
08/22/2022, 12:29 PMSam
08/22/2022, 12:37 PMshift
might depend on whether you are using it to make an Either
, an Effect
, a Validated
, or some other type (e.g. a hypothetical Result
with success/failure semantics).phldavies
08/22/2022, 12:48 PMSam
08/22/2022, 12:50 PMEither<Left, Right>
with shift
or the more concrete Result<Failure, Success>
with fail
.Stylianos Gakis
08/22/2022, 12:57 PMraulraja
08/22/2022, 1:04 PMSinceIt kind of does in it's embedded right bias where it ignores the left to map and flatMap or bind. It's effectively treating the left as an "exceptional" case where it short circuits computations over the structure. The way you describe Either is more like a union type without a bias.doesn’t specify thatEither
means failureleft
I feel like this is a decision on if you want to bring more “normies” like me into the FP world and all the keywords that come with it, or simply make it more accessible for them without necessarily having to teach them these concepts.Yes, I think the goal is in general make it more understandable and accesible to everyone. I can live understanding
CanFail
means Shift
and it's harder to explain Shift from scratch and introduce it.
If it's changed to something failure related, Either should have its subtypes renamed to be aligned. Left and Right are just as detached from the standard use case as Shift is, imo.This one is tricky because of the history behind Either and large usage in not just the arrow community.
Maybe a bigger shift (now that 2.0 is happening is the chance) to go into being more explicit even in the Either case is a good step forwardThere are discussions and work around removing Validated in favor of just Either + the ops that do error accumulation. There is also a new exception handling set of operators that simplify usage of
catch
and attempt
to work over what we are discussing here as Shift or EffectScope. This is all going against an Arrow 2.0. branch
https://github.com/arrow-kt/arrow/pulls?q=is%3Apr+is%3Aopen+label%3A2.0.0phldavies
08/22/2022, 1:06 PMraulraja
08/22/2022, 1:15 PMthrow
where you can exit with any value, not just exceptions. Because most people already understand what throw means. Or frequently, I say shift lets you short circuit the function scope with an alternative value.
Still, the word shift seems subtle and too generic to capture that in most scenarios where people discuss it, it comes up in the context of error propagation and error handling.Marko Novakovic
08/22/2022, 1:48 PMfail
is too similar to throw
which doesn’t make sense to me
when I was starting with FP and Arrow raise
was weird to me for some time, “raising the error into a Left”… weird
shift
makes sense to me, shifts program/function/app flowphldavies
08/22/2022, 2:06 PMsimon.vergauwen
08/22/2022, 2:12 PMFunctor
or Semigroup
but for a newcomer it's not great perse.
It's extremely hard finding a good middle ground, but this feedback is really good to have. Thanks all for sharing. Keep it coming 😁Sam
08/22/2022, 2:17 PMraise
tends to be for errors/exceptions while throw
is for control flow. That might be an argument against using raise
here.sam
08/23/2022, 4:23 AMRaiseError
or Fail
Javier
08/23/2022, 1:59 PMshift
can be other thing different to an error/failure, I think shift
is better. But if it is going to be totally oriented to error/success, CanFail
is more descriptivesam
08/23/2022, 2:08 PMCanFail
because the context is not about if it can fail or not, it's about wrapping an error when something has already failed. The can fail behavior is in the function itself, not the monad error object right?simon.vergauwen
08/23/2022, 2:42 PMThe can fail behavior is in the function itself, not the monad error object right?Uhm... 🤔
NewName
provides the ability to call operation
. In order to call example
one must provide the NewName
"effect" or DSL.
context(NewName<Error>)
suspend fun example(): Int = operation(Error)
effect<Error, Int> { example() }
either<Error, Int> { example() }
option<Int> { catch({ example() }) { _: Error -> shift(None) } }
result<Int> { catch({ example() }) { _: Error -> shift(RuntimeException("error")) } }
The "monad error object" would be effect
, either
, option
, etc, right?
PS: catch
is a new API which name is also still in discussion 😂 See, https://github.com/arrow-kt/arrow/pull/2797rcd27
08/29/2022, 7:08 PMraise
is more intuitive, but this is more from my Python
experience
`For me:Gavin Ray
08/30/2022, 5:08 PMShift
means without looking at docs (maybe it's common FP term)
Raise
(to me) makes it feel like the function's purpose is to raise/throw an error
CanFail
sounds most like "A method which might fail" if that's the intentLukasz Kalnik
09/06/2022, 1:03 PMShortCircuit
?simon.vergauwen
09/06/2022, 1:20 PMshortCircuit
? For CanFail
I'd probably be fail
and for Raise
it would probably be raise
.
I am less concerned about confusing it with Throwable
because you always need to fill in the generic.
This disambiguates the type or error, when you read:
context(Raise<MyError>)
suspend fun program(): Int = raise(MyError)
context(Raise<Unit>)
suspend fun program2(): Int = raise(Unit)
phldavies
09/06/2022, 1:30 PMsimon.vergauwen
09/08/2022, 11:37 AMRaise
for me feels/sounds similar to raise event or raise interrupt so it somehow makes sense to outside of the concept of Throwable
.
I.e. Raise<Event>
, Raise<Interrupt>
, Raise<Error>
have very different meanings to me.
This is not something we need to decide super urgently, so we have some time to let this sink in and re-discuss on a future PR. (Will share in #arrow for sure).
So far it seems Raise
got most votes. Reading this thread it seems that most people already familiar with the concepts feel Raise
it not accurate but grasp the reasoning. Whilst there also seems to be a consensus that Raise
would be most user-friendly for beginners. So this fits within the "requirements" of the name for me.
Sadly, this might be counter-intuitive for any FPers coming to Kotlin/Arrow I think we can mitigate this with a "Guide to Arrow for FPers" (which I am working on alongside trying to figure out this new APIs/names). Additionally, we've seen/experienced that anyone already grasping the patterns/concepts have an relatively easy time getting comfortable with Arrow. Optimising for new comers to FP might be the best approach for the Kotlin, and Arrow community in the long run.