Validation large number of elements #1235
-
While parsing config file, I'm getting some For the prototype I had the code like this Validation<string, Model1> prop1V = ???;
Validation<string, Model2> prop2V = ???;
Validation<string, Config> config = (prop1V, prop2V).Apply((prop1, prop2) => new Config(prop1, prop2)); For the real world example I have the number of props that is larger that is supported, so I cannot use this extension method. Any recommendations how to restructure the code for such large number of props? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
If I understood correctly, you need to create var createConfigComp =
from m1 in Parse(new Model1(1)) // will pass
from m2 in Parse(new Model2(-1)) // will exit with error
select new Config(m1, m2);
createConfigComp.Match(...) // will match on Fail
static Validation<Error, T> Parse<T>(T model) where T : Model =>
model.Value switch
{
>= 0 => Success<Error, T>(model),
_ => Fail<Error, T>(Error.New("Negative value is not valid."))
};
abstract record Model(int Value);
record Model1(int Value) : Model(Value);
record Model2(int Value) : Model(Value);
record Config(Model1 m1, Model2 m2); Here's other discussion on validation. |
Beta Was this translation helpful? Give feedback.
-
The thing to remember is that public record Model1(string W);
public record Model2(string X);
public record Model3(string Y);
public record Model4(string Z);
public record Config(Model1 W, Model2 X, Model3 Y, Model4 Z);
public static class ValidateMany
{
public static Validation<string, Model1> ValidateModel1 =>
...;
public static Validation<string, Model2> ValidateModel2 =>
...;
public static Validation<string, Model3> ValidateModel3 =>
...;
public static Validation<string, Model4> ValidateModel4 =>
...;
public static Validation<string, (Model1 W, Model2 X)> First =>
(ValidateModel1, ValidateModel2).Apply((w, x) => (w, x));
public static Validation<string, (Model3 Y, Model4 Z)> Second =>
(ValidateModel3, ValidateModel4).Apply((y, z) => (y, z));
public static Validation<string, Config> All =>
(First, Second).Apply((fst, snd) => new Config(fst.W, fst.X, snd.Y, snd.Z));
} So, you can see above that You can also use public static Validation<string, (Model1 W, Model2 X)> First =>
(ValidateModel1, ValidateModel2).ApplyM((w, x) => Success<string, (Model1 W, Model2 X)>((w, x))); This allows you to check values in multiple models before propagating either a Finally, if you standardised the configuration system key/values so there's a shared base-type, or a mechanism for pattern-matching and running bespoke validators then you can use the // Simple interface for representing a configuration value. This could instead be something like
// a union-type that you have a single `Validate` function for, doesn't matter really
public interface Value
{
public Validation<string, Value> Validate();
} We can then run public static Validation<string, Map<string, Value>> Validate(Seq<(string Key, Value Value)> values) =>
values.Sequence(item => item.Value.Validate().Map(v => (item.Key, v)))
.Map(items => items.ToMap()); This allows for an extensible set of |
Beta Was this translation helpful? Give feedback.
-
@aloslider @louthy, thanks for your answers! If one interested, I've ended up with writing a similar extension method with the required number of arguments. Monad chaining is not applicable because I need to validate as many fields as possible. Fields are unrelated, so grouping them would confuse colleagues. They do not share base-type. One problem with copy-pasting existing extension method and adding more arguments was that SuccessValue of |
Beta Was this translation helpful? Give feedback.
The thing to remember is that
Validation
is composable. So, you can work with smaller chunks and compose into bigger chunks: