Little thought that probably wouldn't happen... if...
# functional
d
Little thought that probably wouldn't happen... if Kotlin ever decided to let
?.
and
?:
be overridable operators for a non-null type... then it could avoid all the `bind()`s and `flatMap`s and hacks that Arrow is doing... did someone ever propose such a thing? (or maybe some similar operator if people might find it too confusing and think that they're dealing with nullables.)
s
No1 ever proposed this, but we have some things in the work to remove
bind()
and you can already write code that avoids
bind
in 99% of the cases. At

KotlinDevDay

I gave a talk about doing this for
Resource
, and you can do the same for
Either<E, A>
when relying on
Raise<E>
(in 1.2.x or in 1.x.x
EffectScope
). You can achieve the same as
Either.Left(e).bind()
be calling the
raise(e)
DSL. The
Raise
DSL exposes functions to do things like error handling over
E
and
Throwable
etc. So there is not really a need to be-able to override
?
, I think that might make things more confusing.
Raise
,
ResourceScope
, and many other DSLs you can design (and we have in Arrow) can avoid this problem.
These patterns can all be mixed and seamlessly interopt with each-other, since there is also quite some people that prefer having explicit
Either
and
bind
in there code.
d
Truth is, I'm just going over an FP book now, I saw you mentioned shortly
Raise
in the ktor example video, but I for now, I see a code base full of functions with
context(...)
before them, which in this case is just a bit of boilerplate compared to something like an official operator overload...
In the case of services, I'd understand the use of context, but here it's just a technical detail that you need it to compose the either's together...
s
it's just a technical detail that you need it to compose the either's together
Not really, since they're part of your domain. Even with
?
or
?:
you would need some way of tracking the type in the type system. Similar to how nullable types are part of the type system
Int
vs
Int?
. How would you represent that
?
is being used for
MyError
? That is exactly what
Raise<MyError>
does in the
context
(or as extension). Other languages offer deeper integration, or different syntax for
context
. I.e.
Raise[MyError] ?=> Int
in Scala.
Or
Raise[MyError] % Int
using infix types
d
I don't mind the explicit
Either<Error, Success>
in the return type as much as the clutter of nested flatmaps... the context receivers of
Raise
work at getting rid of the return type as well as the flatmaps...
At the cost of adding to the context declaration not only real dependencies, but also a different concept of error case handling aka
@Throws
FP style... I'm sure others would love that and it wouldn't bother them... I'm just wondering if for the some that don't mind/want explicitness in the returning type there could be something "in the middle" not too cluttery, not too implicit.
Yeah, but one way or the other, the problem with
?.
would be that you'd still have to get the result from the previous computation:
getUsers(...)?.let  { getAddress(it) }
so it doesn't really save anything apart from looking a bit more like a standard "I didn't get something valid from the previous computation (null = Left...)"