Hello, I have a set of functions that validate som...
# arrow
o
Hello, I have a set of functions that validate some object. I zip those to get a Validated and use them in an either block. Now I am wondering, what the most idiomatic way to enabling 1-n of those functions via a configuration file would be. In the end, I need to get from a list of Booleans (validationX enabled?) to a list of validation functions, that need to get zipped for a result ...writing it in pseudocode...Either<InvalidFoo(reasons: Nel<Plausibility>>, ValidFoo>. Any ideas?
s
1-n of those functions via a configuration file would be.
You mean generating
Validated.zip
for more than 9 parameters? It's probably quite easy to write a little KScript that generates it, that is sadly the annoying thing about
zip
and
n-arity
functions like this in Kotlin. There is however another way of composing
zip
to achieve higher arities that is quite simple.
Copy code
validatedA.zip(
  validatedB,
  validatedC.zip(vaidatedD, ::Pair)
) { a, b, (c, d) -> ... }
By nesting zip2 inside another zip2 and using an intermediate
Tuple
you can compose 2x
zip2
to achieve
zip4
. Same is applicable for
zip9 + zip9
to get
arity-18
.
o
Thank you for the good tip, but the arity is not a problem...at least atm. 🙂 🙌 What I am trying to achieve, is to write a function / or use one from Arrow if there is one, that takes some Booleans from a config file - e.g. doValidateFoo: true, doValidateBar: true, doValidateBaz: false - and zips only the corresponding functions: If doValidateBar and doValidateBaz in the config file would be true, I want to run validateBar().zip(validateBaz()) {ValidSomething(this)}.mapLeft{InvalidSomething(errors=it)} in the code. I guess I need to fold a list of validateX functions, but I wanted to check if there's like an Arrow idiomatic way to do this.
s
If you just need to run a bunch of validations in a list maybe you could do something like this, but I'm not sure how you're loading the data / functions. If you have a
List<() -> Validated<E, A>>
than you can turn it into
Validated<E, List<A>>
by using
traverse
, an extension on
Iterable
. Depending on how you load the booleans/functions from the config you could perhaps do something like.
Copy code
val config: List<Pair<Boolean, () -> Validated<E, A>>> = ....

val validationsToRun: List<() -> Validated<E, A>> =
  config.mapNotNull { (boolean, function) -> function.takeIf { boolean } }

val result = validationsToRun.traverse { f -> f() }
s
Might wanna take a look at https://github.com/sksamuel/hoplite
o
Thank you @simon.vergauwen! List<Pair<Boolean, () -> Validated<E,A>> and accumulating the functions to run seems perfect. I've defined validations as extensions on A but that doesn't matter. I will try where traversing the functions get's me, thanks a lot.
I am kinda stuck on this... 😨 Started with
val config: List<Pair<Boolean, (Thing) -> ValidatedNel<E, Thing>>>
and when I traverse those functions like in the example above, I get a
List<Thing>
where I would like to have a
Thing
. Zip does not work on lists of functions with arbitrary length...I must be missing something. 🤔 I also don't get why @simon.vergauwen chose validations functions to be
() -> Validated<E,A>
? Does that mean my approach with passing or extending from the thing to validate is wrong?
s
Hey @Oliver Eisenbarth, The reason for my types, and signatures is because I don't know a lot about your use-case. So that was based on a lot of assumptions. If you can share some snippets, or functions with signatures I could give you a more precise answer ☺️
o
Hi Simon, thanks for helping out. Unfortunately I can't copy paste code because of NDA, but I'll try to set up a personal project that shows the problem asap - who knows, maybe I can make a first blog article from it. 🙂 May I ping you again then or is that annoying? I really don't know how to behave here, please excuse. 😊
s
No worries Oliver! ☺️ Yes, of course you can ping me. If you can share the function signatures, that would also be sufficient I think. You can replace any details with an unrelated domain.