Hi. Just wanted to check if adding a method for co...
# arrow
m
Hi. Just wanted to check if adding a method for combining validated instances has been considered? In cats there is a method called
andThen
which would be nice to have in arrow. Currently one can achieve something functionally equal with
withEither
like this:
Copy code
Validated.catch { "0".toInt() }.toValidatedNel().withEither { it.flatMap { Either.catch { 1 / it } }
however going through an either instance feels unnecessary when one is still operating on validations. So perhaps something like this:
Copy code
fun <E,A, B> Validated<E, A>.andThen(f: (A) -> Validated<E, B>) :Validated<E, B> {
  return when(this){
    is Valid -> f(value)
    is Invalid -> this
  }
}

Validated.catch { "0".toInt() }.toValidatedNel().andThen { Validated.catch { 1/it } }
Example is a simple, but it is quite useful when you want to do input validation first, and then if valid continue with more advanced validation rules
s
Hey @Morten Andersen-Gott, We’ve considered this but haven’t explicitly added it. You can however leverage the
either { }
DSL to
bind
Validated
in the same style a
either
(using short-circuit). So that gives you the same behavior as
andThen
or going through
Either
without actually paying for it. (it just folds under the hood).
Copy code
either {
  val x = Validated.catch { "0".toInt() }.bind()
  val y = Validated.catch { 1 / x }.bind()
  y
}
This allows you to combine
Validated
programs in the style you mention.
That being said, I don’t think adding a single method to
Validated
like this would hurt. As you’ve shown here
withEither { }
is a bit cumbersome.
👍 2
m
If you'd consider this, would you like it submitted as a PR?
s
A PR would be great! ❤️ An issue would also be welcome of course if you want to discuss it first, or want to propose/discuss it. The biggest goal towards 2.0 is making Arrow even more idiomatic in Kotlin, and getting as much user feedback as possible to make the APIs more meaningful like exactly this 👍
❤️ 3
m
@simon.vergauwen started looking at a PR this weekend. Am I right in understanding that the andThen has to be a extension method as long as E is covariant?
😍 1
s
Yes, that is correct. By declaring it as an extension function you effectively “recapture” the
E
and you can by-pass the restriction of
out E
as defined in the
class
.
👍 1
j
@simon.vergauwen what do you think about infix functions?
Not sure if you like the infix syntax:
Copy code
Valid(5) andThen Valid(10)
Or even
Copy code
Valid(5) then Valid(10)
m
s
I like
infix
, but when working with lambdas I don’t find them super useful. I don’t think
Valid(5) andThen { x: X -> Valid(x + 1) }
reads much better then
Valid(5).andThen { }
but that can be left up to the user. It’s an approach we haven’t commonly taking since this breaks chain-ability.
Valid(5) andThen { x: X -> Valid(x + 1) }.map { it + 3 }
this code is invalid.
(Valid(5) andThen { x: X -> Valid(x + 1) }).map { it + 3 }
now this code is valid.
👍 1
I’ll review it asap @Morten Andersen-Gott. Thanks for the contribution 🙏
m
Had some issues getting the site build to work (
/vendor/bundle/ruby/3.0.0/gems/kramdown-1.17.0/lib/kramdown/parser/html.rb:10:in require: cannot load such file -- rexml/parsers/baseparser (LoadError)
), so haven’t been able to do a visual review of the generated docs.
👍 1
s
That’s not a problem. I can double check that for you
🙏 1