simon.vergauwen
11/28/2022, 10:41 AMValidated
and integrating its functionality into Either
. https://github.com/arrow-kt/arrow/pull/2795#issuecomment-1328864003
Feedback, and thoughts are very welcome 🙏stojan
11/28/2022, 12:39 PMzip
function instead of the current extension function?
I think it existed in earlier versions of arrow but was replaced by extension functions at one point
e.g. zip
and combine
from kotlinx coroutines are top level functionssimon.vergauwen
11/28/2022, 12:48 PMzip(fa, fb, fc) { a, b, c -> }
instead of fa.zip(fb, fc) { a, b, c -> }
?simon.vergauwen
11/28/2022, 12:49 PMzip
. I.e. on Iterable<A>
stojan
11/28/2022, 12:59 PMIterable
example, it's always two of them that are zipped... so extension function makes sense there IMO
but when we have them with arity 2-7, top level makes more sense IMOsimon.vergauwen
11/28/2022, 1:05 PMsimon.vergauwen
11/28/2022, 1:06 PMcombine
is defined as an extension for arity-2 and for arity 3+ it's top-level 🤯
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/combine.htmlsimon.vergauwen
11/28/2022, 1:07 PMvararg
which is different, since that doesn't allow independent functions like Either#zip
.stojan
11/28/2022, 1:10 PMstojan
11/28/2022, 1:11 PMI wish there were guidelines for this, or that the Jetbrains people would document why these functions are shaped differently in Kotlin Std and KotlinX.maybe we can ask in the #stdlib channel?
simon.vergauwen
11/28/2022, 1:11 PMflowA.zip(flowB) { a, b -> }
to zip(flowA, flowB, flowC) { a, b, c -> }
stojan
11/28/2022, 1:15 PMphldavies
11/28/2022, 2:15 PMValidated<A>.zip(b: V<B>, c: V<C>, (A, B, C) -> R)
odd that it feels like it elevates A
other the others as different. If you want to rearrange the arguments to the block you end up swapping receivers around.simon.vergauwen
11/28/2022, 2:17 PMphldavies
11/28/2022, 3:33 PMval username = fields.required("username").andThen(String::parseUsername)
val email = fields.required("email").andThen(String::parseEmail)
val age = fields.required("age").andThen(String::parseAge)
email.zip(username, age, ::CreateUserRequest)
Why is email
different to username
or age
in this case? If I wanted to updated CreateUserRequest
to take username
first, I’d need to update the receiver of zip
rather than just the argument ordering. It just feels like the first argument being bound is treated specially. For this reason, I sometimes find myself adding a top-level zip(A, B, C, (a, b, c) -> R)
helper to make it feel a little more natural. As an example, kotest has a top-level Arb.bind(Gen<A>, Gen<B>, Gen<C>, (a, b, c) -> R) -> Arb<R>
rather than a Gen<A>.zip(...)
simon.vergauwen
11/28/2022, 3:39 PMEither.zip(fa, fb, fc) { a, b, c -> }
would make more sense to you? I guess this is similar to what @stojan was saying.
One of the original reasoning, besides getting inspiration from Iterable<A>#zip
was because fa.zip
is easier to find through auto-completion.phldavies
11/28/2022, 3:50 PMValidated
I initially looked for an extension off the Validated
companion, iirc.
I can certainly see your reasoning though, given stdlib provides Iterable<A>.zip(Iterable<B>, (A, B) -> C)
and arrow extends that with n-arity forms with the receiver maintained.simon.vergauwen
11/28/2022, 3:51 PMmapN(fa, fb, fc) { a, b, c -> }
or with special syntax fa @ fb @ fc
(returning a Tuple).stojan
11/28/2022, 3:52 PMI initially looked for an extension off theAFIK the companion object strategy is not used in the standard lib or kotlinx coroutines, and the kotlin team suggests top level functions insteadcompanionValidated