/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.control; import io.vavr.*; import io.vavr.collection.Seq; import io.vavr.collection.Iterator; import io.vavr.collection.List; import java.io.Serializable; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * An implementation similar to scalaz's <a href="http://eed3si9n.com/learning-scalaz/Validation.html">Validation</a> control. * * <p> * The Validation type is different from a Monad type, it is an applicative * functor. Whereas a Monad will short circuit after the first error, the * applicative functor will continue on, accumulating ALL errors. This is * especially helpful in cases such as validation, where you want to know * all the validation errors that have occurred, not just the first one. * </p> * * <pre> * <code> * <b>Validation construction:</b> * * <i>Valid:</i> * Validation<String,Integer> valid = Validation.valid(5); * * <i>Invalid:</i> * Validation<List<String>,Integer> invalid = Validation.invalid(List.of("error1","error2")); * * <b>Validation combination:</b> * * Validation<String,String> valid1 = Validation.valid("John"); * Validation<String,Integer> valid2 = Validation.valid(5); * Validation<String,Option<String>> valid3 = Validation.valid(Option.of("123 Fake St.")); * Function3<String,Integer,Option<String>,Person> f = ...; * * Validation<List<String>,String> result = valid1.combine(valid2).ap((name,age) -> "Name: "+name+" Age: "+age); * Validation<List<String>,Person> result2 = valid1.combine(valid2).combine(valid3).ap(f); * * <b>Another form of combining validations:</b> * * Validation<List<String>,Person> result3 = Validation.combine(valid1, valid2, valid3).ap(f); * </code> * </pre> * * @param <E> value type in the case of invalid * @param <T> value type in the case of valid * @author Eric Nelson * @see <a href="https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/Validation.scala">Validation</a> */ public interface Validation<E, T> extends Value<T>, Serializable { long serialVersionUID = 1L; /** * Creates a {@link Valid} that contains the given {@code value}. * * @param <E> type of the error * @param <T> type of the given {@code value} * @param value A value * @return {@code Valid(value)} */ static <E, T> Validation<E, T> valid(T value) { return new Valid<>(value); } /** * Creates an {@link Invalid} that contains the given {@code error}. * * @param <E> type of the given {@code error} * @param <T> type of the value * @param error An error * @return {@code Invalid(error)} * @throws NullPointerException if error is null */ static <E, T> Validation<E, T> invalid(E error) { Objects.requireNonNull(error, "error is null"); return new Invalid<>(error); } /** * Creates a {@code Validation} of an {@code Either}. * * @param either An {@code Either} * @param <E> type of the given {@code error} * @param <T> type of the value * @return A {@code Valid(either.get())} if either is a Right, otherwise {@code Invalid(either.getLeft())}. * @throws NullPointerException if either is null */ static <E, T> Validation<E, T> fromEither(Either<E, T> either) { Objects.requireNonNull(either, "either is null"); return either.isRight() ? valid(either.get()) : invalid(either.getLeft()); } /** * Reduces many {@code Validation} instances into a single {@code Validation} by transforming an * {@code Iterable<Validation<? extends T>>} into a {@code Validation<Seq<T>>}. * * @param <E> value type in the case of invalid * @param <T> value type in the case of valid * @param values An iterable of Validation instances. * @return A valid Validation of a sequence of values if all Validation instances are valid * or an invalid Validation containing an accumulated List of errors. * @throws NullPointerException if values is null */ static <E, T> Validation<Seq<E>, Seq<T>> sequence(Iterable<? extends Validation<Seq<E>, T>> values) { Objects.requireNonNull(values, "values is null"); List<E> errors = List.empty(); List<T> list = List.empty(); for (Validation<Seq<E>, T> value : values) { if (value.isInvalid()) { errors = errors.prependAll(value.getError().reverse()); } else if (errors.isEmpty()) { list = list.prepend(value.get()); } } return errors.isEmpty() ? valid(list.reverse()) : invalid(errors.reverse()); } /** * Narrows a widened {@code Validation<? extends E, ? extends T>} to {@code Validation<E, T>} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param validation A {@code Validation}. * @param <E> type of error * @param <T> type of valid value * @return the given {@code validation} instance as narrowed type {@code Validation<E, T>}. */ @SuppressWarnings("unchecked") static <E, T> Validation<E, T> narrow(Validation<? extends E, ? extends T> validation) { return (Validation<E, T>) validation; } /** * Combines two {@code Validation}s into a {@link Builder}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param validation1 first validation * @param validation2 second validation * @return an instance of Builder<E,T1,T2> * @throws NullPointerException if validation1 or validation2 is null */ static <E, T1, T2> Builder<E, T1, T2> combine(Validation<E, T1> validation1, Validation<E, T2> validation2) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); return new Builder<>(validation1, validation2); } /** * Combines three {@code Validation}s into a {@link Builder3}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @return an instance of Builder3<E,T1,T2,T3> * @throws NullPointerException if validation1, validation2 or validation3 is null */ static <E, T1, T2, T3> Builder3<E, T1, T2, T3> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); return new Builder3<>(validation1, validation2, validation3); } /** * Combines four {@code Validation}s into a {@link Builder4}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param <T4> type of fourth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @return an instance of Builder3<E,T1,T2,T3,T4> * @throws NullPointerException if validation1, validation2, validation3 or validation4 is null */ static <E, T1, T2, T3, T4> Builder4<E, T1, T2, T3, T4> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3, Validation<E, T4> validation4) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); return new Builder4<>(validation1, validation2, validation3, validation4); } /** * Combines five {@code Validation}s into a {@link Builder5}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param <T4> type of fourth valid value * @param <T5> type of fifth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5> * @throws NullPointerException if validation1, validation2, validation3, validation4 or validation5 is null */ static <E, T1, T2, T3, T4, T5> Builder5<E, T1, T2, T3, T4, T5> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3, Validation<E, T4> validation4, Validation<E, T5> validation5) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); return new Builder5<>(validation1, validation2, validation3, validation4, validation5); } /** * Combines six {@code Validation}s into a {@link Builder6}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param <T4> type of fourth valid value * @param <T5> type of fifth valid value * @param <T6> type of sixth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5 or validation6 is null */ static <E, T1, T2, T3, T4, T5, T6> Builder6<E, T1, T2, T3, T4, T5, T6> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3, Validation<E, T4> validation4, Validation<E, T5> validation5, Validation<E, T6> validation6) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); return new Builder6<>(validation1, validation2, validation3, validation4, validation5, validation6); } /** * Combines seven {@code Validation}s into a {@link Builder7}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param <T4> type of fourth valid value * @param <T5> type of fifth valid value * @param <T6> type of sixth valid value * @param <T7> type of seventh valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @param validation7 seventh validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6 or validation7 is null */ static <E, T1, T2, T3, T4, T5, T6, T7> Builder7<E, T1, T2, T3, T4, T5, T6, T7> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3, Validation<E, T4> validation4, Validation<E, T5> validation5, Validation<E, T6> validation6, Validation<E, T7> validation7) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); Objects.requireNonNull(validation7, "validation7 is null"); return new Builder7<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7); } /** * Combines eight {@code Validation}s into a {@link Builder8}. * * @param <E> type of error * @param <T1> type of first valid value * @param <T2> type of second valid value * @param <T3> type of third valid value * @param <T4> type of fourth valid value * @param <T5> type of fifth valid value * @param <T6> type of sixth valid value * @param <T7> type of seventh valid value * @param <T8> type of eighth valid value * @param validation1 first validation * @param validation2 second validation * @param validation3 third validation * @param validation4 fourth validation * @param validation5 fifth validation * @param validation6 sixth validation * @param validation7 seventh validation * @param validation8 eighth validation * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7,T8> * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6, validation7 or validation8 is null */ static <E, T1, T2, T3, T4, T5, T6, T7, T8> Builder8<E, T1, T2, T3, T4, T5, T6, T7, T8> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3, Validation<E, T4> validation4, Validation<E, T5> validation5, Validation<E, T6> validation6, Validation<E, T7> validation7, Validation<E, T8> validation8) { Objects.requireNonNull(validation1, "validation1 is null"); Objects.requireNonNull(validation2, "validation2 is null"); Objects.requireNonNull(validation3, "validation3 is null"); Objects.requireNonNull(validation4, "validation4 is null"); Objects.requireNonNull(validation5, "validation5 is null"); Objects.requireNonNull(validation6, "validation6 is null"); Objects.requireNonNull(validation7, "validation7 is null"); Objects.requireNonNull(validation8, "validation8 is null"); return new Builder8<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7, validation8); } /** * Check whether this is of type {@code Valid} * * @return true if is a Valid, false if is an Invalid */ boolean isValid(); /** * Check whether this is of type {@code Invalid} * * @return true if is an Invalid, false if is a Valid */ boolean isInvalid(); /** * Returns this {@code Validation} if it is valid, otherwise return the alternative. * * @param other An alternative {@code Validation} * @return this {@code Validation} if it is valid, otherwise return the alternative. */ @SuppressWarnings("unchecked") default Validation<E, T> orElse(Validation<? extends E, ? extends T> other) { Objects.requireNonNull(other, "other is null"); return isValid() ? this : (Validation<E, T>) other; } /** * Returns this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. * * @param supplier An alternative {@code Validation} supplier * @return this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. */ @SuppressWarnings("unchecked") default Validation<E, T> orElse(Supplier<Validation<? extends E, ? extends T>> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isValid() ? this : (Validation<E, T>) supplier.get(); } @Override default boolean isEmpty() { return isInvalid(); } /** * Gets the value of this {@code Validation} if is a {@code Valid} or throws if this is an {@code Invalid}. * * @return The value of this {@code Validation} * @throws NoSuchElementException if this is an {@code Invalid} */ @Override T get(); /** * Gets the value if it is a Valid or an value calculated from the error * * @param other a function which converts an error to an alternative value * @return the value, if the underlying Validation is a Valid, or else the alternative value * provided by {@code other} by applying the error. */ default T getOrElseGet(Function<? super E, ? extends T> other) { Objects.requireNonNull(other, "other is null"); if (isValid()) { return get(); } else { return other.apply(getError()); } } /** * Gets the error of this Validation if is an Invalid or throws if this is a Valid * * @return The error of this Invalid * @throws RuntimeException if this is a Valid */ E getError(); /** * Returns this as {@code Either}. * * @return {@code Either.right(get())} if this is valid, otherwise {@code Either.left(getError())}. */ default Either<E, T> toEither() { return isValid() ? Either.right(get()) : Either.left(getError()); } @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); /** * Performs the given action for the value contained in {@code Valid}, or do nothing * if this is an Invalid. * * @param action the action to be performed on the contained value * @throws NullPointerException if action is null */ @Override default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action, "action is null"); if (isValid()) { action.accept(get()); } } /** * Performs the action in {@code fInvalid} on {@code error} if this is an {@code Invalid}, * or {@code fValid} on {@code value} if this is a {@code Valid}. * Returns an object of type U. * * <p> * <code> * For example:<br> * Validation<List<String>,String> valid = ...;<br> * Integer i = valid.fold(List::length, String::length); * </code> * </p> * * @param <U> the fold result type * @param fInvalid the invalid fold operation * @param fValid the valid fold operation * @return an instance of type U * @throws NullPointerException if fInvalid or fValid is null */ default <U> U fold(Function<? super E, ? extends U> fInvalid, Function<? super T, ? extends U> fValid) { Objects.requireNonNull(fInvalid, "fInvalid is null"); Objects.requireNonNull(fValid, "fValid is null"); if (isInvalid()) { final E error = this.getError(); return fInvalid.apply(error); } else { final T value = this.get(); return fValid.apply(value); } } /** * Flip the valid/invalid values for this Validation. If this is a Valid<E,T>, returns Invalid<T,E>. * Or if this is an Invalid<E,T>, return a Valid<T,E>. * * @return a flipped instance of Validation */ default Validation<T, E> swap() { if (isInvalid()) { final E error = this.getError(); return Validation.valid(error); } else { final T value = this.get(); return Validation.invalid(value); } } @Override default <U> Validation<E, U> map(Function<? super T, ? extends U> f) { Objects.requireNonNull(f, "f is null"); if (isInvalid()) { return Validation.invalid(this.getError()); } else { final T value = this.get(); return Validation.valid(f.apply(value)); } } /** * Whereas map only performs a mapping on a valid Validation, and mapError performs a mapping on an invalid * Validation, bimap allows you to provide mapping actions for both, and will give you the result based * on what type of Validation this is. Without this, you would have to do something like: * * validation.map(...).mapError(...); * * @param <E2> type of the mapping result if this is an invalid * @param <T2> type of the mapping result if this is a valid * @param errorMapper the invalid mapping operation * @param valueMapper the valid mapping operation * @return an instance of Validation<U,R> * @throws NullPointerException if invalidMapper or validMapper is null */ default <E2, T2> Validation<E2, T2> bimap(Function<? super E, ? extends E2> errorMapper, Function<? super T, ? extends T2> valueMapper) { Objects.requireNonNull(errorMapper, "errorMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); if (isInvalid()) { final E error = this.getError(); return Validation.invalid(errorMapper.apply(error)); } else { final T value = this.get(); return Validation.valid(valueMapper.apply(value)); } } /** * Applies a function f to the error of this Validation if this is an Invalid. Otherwise does nothing * if this is a Valid. * * @param <U> type of the error resulting from the mapping * @param f a function that maps the error in this Invalid * @return an instance of Validation<U,T> * @throws NullPointerException if mapping operation f is null */ default <U> Validation<U, T> mapError(Function<? super E, ? extends U> f) { Objects.requireNonNull(f, "f is null"); if (isInvalid()) { final E error = this.getError(); return Validation.invalid(f.apply(error)); } else { return Validation.valid(this.get()); } } default <U> Validation<Seq<E>, U> ap(Validation<Seq<E>, ? extends Function<? super T, ? extends U>> validation) { Objects.requireNonNull(validation, "validation is null"); if (isValid()) { if (validation.isValid()) { final Function<? super T, ? extends U> f = validation.get(); final U u = f.apply(this.get()); return valid(u); } else { final Seq<E> errors = validation.getError(); return invalid(errors); } } else { if (validation.isValid()) { final E error = this.getError(); return invalid(List.of(error)); } else { final Seq<E> errors = validation.getError(); final E error = this.getError(); return invalid(errors.append(error)); } } } /** * Combines two {@code Validation}s to form a {@link Builder}, which can then be used to perform further * combines, or apply a function to it in order to transform the {@link Builder} into a {@code Validation}. * * @param <U> type of the value contained in validation * @param validation the validation object to combine this with * @return an instance of Builder */ default <U> Builder<E, T, U> combine(Validation<E, U> validation) { return new Builder<>(this, validation); } // -- Implementation of Value default Option<Validation<E, T>> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isInvalid() || predicate.test(get()) ? Option.some(this) : Option.none(); } @SuppressWarnings("unchecked") default <U> Validation<E, U> flatMap(Function<? super T, ? extends Validation<E, ? extends U>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isInvalid() ? (Validation<E, U>) this : (Validation<E, U>) mapper.apply(get()); } @Override default Validation<E, T> peek(Consumer<? super T> action) { if (isValid()) { action.accept(get()); } return this; } /** * A {@code Validation}'s value is computed synchronously. * * @return false */ @Override default boolean isAsync() { return false; } /** * A {@code Validation}'s value is computed eagerly. * * @return false */ @Override default boolean isLazy() { return false; } @Override default boolean isSingleValued() { return true; } @Override default Iterator<T> iterator() { return isValid() ? Iterator.of(get()) : Iterator.empty(); } /** * A valid Validation * * @param <E> type of the error of this Validation * @param <T> type of the value of this Validation */ final class Valid<E, T> implements Validation<E, T>, Serializable { private static final long serialVersionUID = 1L; private final T value; /** * Construct a {@code Valid} * * @param value The value of this success */ private Valid(T value) { this.value = value; } @Override public boolean isValid() { return true; } @Override public boolean isInvalid() { return false; } @Override public T get() { return value; } @Override public E getError() throws RuntimeException { throw new NoSuchElementException("error of 'valid' Validation"); } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Valid && Objects.equals(value, ((Valid<?, ?>) obj).value)); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String stringPrefix() { return "Valid"; } @Override public String toString() { return stringPrefix() + "(" + value + ")"; } } /** * An invalid Validation * * @param <E> type of the error of this Validation * @param <T> type of the value of this Validation */ final class Invalid<E, T> implements Validation<E, T>, Serializable { private static final long serialVersionUID = 1L; private final E error; /** * Construct an {@code Invalid} * * @param error The value of this error */ private Invalid(E error) { this.error = error; } @Override public boolean isValid() { return false; } @Override public boolean isInvalid() { return true; } @Override public T get() throws RuntimeException { throw new NoSuchElementException("get of 'invalid' Validation"); } @Override public E getError() { return error; } @Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Invalid && Objects.equals(error, ((Invalid<?, ?>) obj).error)); } @Override public int hashCode() { return Objects.hashCode(error); } @Override public String stringPrefix() { return "Invalid"; } @Override public String toString() { return stringPrefix() + "(" + error + ")"; } } final class Builder<E, T1, T2> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Builder(Validation<E, T1> v1, Validation<E, T2> v2) { this.v1 = v1; this.v2 = v2; } public <R> Validation<Seq<E>, R> ap(Function2<T1, T2, R> f) { return v2.ap(v1.ap(Validation.valid(f.curried()))); } public <T3> Builder3<E, T1, T2, T3> combine(Validation<E, T3> v3) { return new Builder3<>(v1, v2, v3); } } final class Builder3<E, T1, T2, T3> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Builder3(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3) { this.v1 = v1; this.v2 = v2; this.v3 = v3; } public <R> Validation<Seq<E>, R> ap(Function3<T1, T2, T3, R> f) { return v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))); } public <T4> Builder4<E, T1, T2, T3, T4> combine(Validation<E, T4> v4) { return new Builder4<>(v1, v2, v3, v4); } } final class Builder4<E, T1, T2, T3, T4> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Validation<E, T4> v4; private Builder4(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3, Validation<E, T4> v4) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; } public <R> Validation<Seq<E>, R> ap(Function4<T1, T2, T3, T4, R> f) { return v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))); } public <T5> Builder5<E, T1, T2, T3, T4, T5> combine(Validation<E, T5> v5) { return new Builder5<>(v1, v2, v3, v4, v5); } } final class Builder5<E, T1, T2, T3, T4, T5> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Validation<E, T4> v4; private Validation<E, T5> v5; private Builder5(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3, Validation<E, T4> v4, Validation<E, T5> v5) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; } public <R> Validation<Seq<E>, R> ap(Function5<T1, T2, T3, T4, T5, R> f) { return v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))))); } public <T6> Builder6<E, T1, T2, T3, T4, T5, T6> combine(Validation<E, T6> v6) { return new Builder6<>(v1, v2, v3, v4, v5, v6); } } final class Builder6<E, T1, T2, T3, T4, T5, T6> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Validation<E, T4> v4; private Validation<E, T5> v5; private Validation<E, T6> v6; private Builder6(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3, Validation<E, T4> v4, Validation<E, T5> v5, Validation<E, T6> v6) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; } public <R> Validation<Seq<E>, R> ap(Function6<T1, T2, T3, T4, T5, T6, R> f) { return v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))))); } public <T7> Builder7<E, T1, T2, T3, T4, T5, T6, T7> combine(Validation<E, T7> v7) { return new Builder7<>(v1, v2, v3, v4, v5, v6, v7); } } final class Builder7<E, T1, T2, T3, T4, T5, T6, T7> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Validation<E, T4> v4; private Validation<E, T5> v5; private Validation<E, T6> v6; private Validation<E, T7> v7; private Builder7(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3, Validation<E, T4> v4, Validation<E, T5> v5, Validation<E, T6> v6, Validation<E, T7> v7) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; this.v7 = v7; } public <R> Validation<Seq<E>, R> ap(Function7<T1, T2, T3, T4, T5, T6, T7, R> f) { return v7.ap(v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried())))))))); } public <T8> Builder8<E, T1, T2, T3, T4, T5, T6, T7, T8> combine(Validation<E, T8> v8) { return new Builder8<>(v1, v2, v3, v4, v5, v6, v7, v8); } } final class Builder8<E, T1, T2, T3, T4, T5, T6, T7, T8> { private Validation<E, T1> v1; private Validation<E, T2> v2; private Validation<E, T3> v3; private Validation<E, T4> v4; private Validation<E, T5> v5; private Validation<E, T6> v6; private Validation<E, T7> v7; private Validation<E, T8> v8; private Builder8(Validation<E, T1> v1, Validation<E, T2> v2, Validation<E, T3> v3, Validation<E, T4> v4, Validation<E, T5> v5, Validation<E, T6> v6, Validation<E, T7> v7, Validation<E, T8> v8) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.v4 = v4; this.v5 = v5; this.v6 = v6; this.v7 = v7; this.v8 = v8; } public <R> Validation<Seq<E>, R> ap(Function8<T1, T2, T3, T4, T5, T6, T7, T8, R> f) { return v8.ap(v7.ap(v6.ap(v5.ap(v4.ap(v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))))))); } } }