<https://imgflip.com/i/6v3rs0> Evolving the Eithe...
# arrow
s
https://imgflip.com/i/6v3rs0 Evolving the Either API for Arrow 2.0, we want to reduce the API surface so that we can offer uniform APIs and simply the learning curve for everyone. https://github.com/arrow-kt/arrow/pull/2830
👍 2
😂 3
r
Looked over the files, all the deprecations and changes look good to me. If
foldMap
is going away presumably because working with Monoid or type classes is a pain, should we also get rid of Monoid etc? or are those still useful for other things?
s
TBH I don't think
Monoid
and
Semigroup
still offer a lot of value.
Semigroup
is a glorified
(A, A) -> A
function, and similar for
Monoid
. Working with
Iterable
and data types is simplified a lot with the new APIs.
traverse
is
map
+
bind
, and accumulating is
mapAccumulating { either() }
. That would be outside of the scope of this PR, but absolutely something we can consider for 2.0 (and deprecation in 1.x.x)
t
Agree, with our current direction, Monoid and Semigroup don't add much value anymore. Removing them also reducing confusion for new comers.
s
I thought Semigroup gives a collection of left hand side when used with zip. Thus deprecating Validate in favor of Either<List<E>, A> would be okay. But is my understanding wrong ?
r
in that case the Semigroup is just there in case you want to accumulate into a custom type that is not a
NonEmptyList
, but since by default error accumulation happens in a non-empty list and how to combine non-empty list (their semigroup) is known, we don't need that extra semigroup param or expose it to users.
But is my understanding wrong ?
I think it's right, we are getting rid of Validated and error accumulation will happen naturally without having to provide a semigroup.
s
The base signature will look like this (up to arity-9)
Copy code
Either<E, A>.zip(other: Either<E, B>, combine: (E, E) -> E, transform: (A, B) -> C): Either<E, C>
Either<E, A>.zip(other: Either<E, B>, transform: (A, B) -> C): Either<Nel<E>, C>

Iterable<A>.mapAccumulating(combine: (E, E) -> E, transform: (A) -> Either<E, B>): Either<E, List<B>>
Iterable<A>.mapAccumulating(transform: (A) -> Either<E, B>): Either<Nel<E>, List<B>>
The new
either
DSL will be
inline
so no more need for
eager
or
invoke
and you can just add
suspend
wherever needed ad-hoc. Using the DSL will have the same cost as a single
map
, so it can be used everywhere without any performance hits.
s
nice