001    package fj.data;
002    
003    import fj.Effect;
004    import fj.F;
005    import fj.F2;
006    import fj.F3;
007    import fj.F4;
008    import fj.F5;
009    import fj.F6;
010    import fj.F7;
011    import fj.F8;
012    import static fj.Function.curry;
013    import static fj.P.p;
014    import fj.P1;
015    import fj.Unit;
016    import static fj.Unit.unit;
017    import static fj.Bottom.error;
018    import fj.pre.Semigroup;
019    
020    import java.util.Iterator;
021    
022    /**
023     * Isomorphic to {@link Either} but has renamed functions and represents failure on the left and success on the right.
024     * This type also has accumulating functions that accept a {@link Semigroup} for binding computation while keeping error
025     * values
026     *
027     * @version %build.number%<br>
028     *          <ul>
029     *          <li>$LastChangedRevision: 163 $</li>
030     *          <li>$LastChangedDate: 2009-06-02 03:43:12 +1000 (Tue, 02 Jun 2009) $</li>
031     *          </ul>
032     */
033    public final class Validation<E, T> implements Iterable<T> {
034      private final Either<E, T> e;
035    
036      private Validation(final Either<E, T> e) {
037        this.e = e;
038      }
039    
040      /**
041       * Returns <code>true</code> if this is a failure, <code>false</code> otherwise.
042       *
043       * @return <code>true</code> if this is a failure, <code>false</code> otherwise.
044       */
045      public boolean isFail() {
046        return e.isLeft();
047      }
048    
049      /**
050       * Returns <code>true</code> if this is a success, <code>false</code> otherwise.
051       *
052       * @return <code>true</code> if this is a success, <code>false</code> otherwise.
053       */
054      public boolean isSuccess() {
055        return e.isRight();
056      }
057    
058      /**
059       * Returns the failing value, or throws an error if there is no failing value.
060       *
061       * @return the failing value, or throws an error if there is no failing value.
062       */
063      public E fail() {
064        if (isFail())
065          return e.left().value();
066        else
067          throw error("Validation: fail on success value");
068      }
069    
070      /**
071       * Returns the success value, or throws an error if there is no success value.
072       *
073       * @return the success value, or throws an error if there is no success value.
074       */
075      public T success() {
076        if (isSuccess())
077          return e.right().value();
078        else
079          throw error("Validation: success on fail value");
080      }
081    
082      /**
083       * The catamorphism for validation. Folds over this validation breaking into left or right.
084       *
085       * @param fail    The function to call if this failed.
086       * @param success The function to call if this succeeded.
087       * @return The reduced value.
088       */
089      public <X> X validation(final F<E, X> fail, final F<T, X> success) {
090        return e.either(fail, success);
091      }
092    
093      /**
094       * Returns a failing projection of this validation.
095       *
096       * @return a failing projection of this validation.
097       */
098      public FailProjection<E, T> f() {
099        return new FailProjection<E, T>(this);
100      }
101    
102      /**
103       * Returns an either projection of this validation.
104       *
105       * @return An either projection of this validation.
106       */
107      public Either<E, T> toEither() {
108        return e;
109      }
110    
111      /**
112       * Returns the success value or fails with the given error message.
113       *
114       * @param err The error message to fail with.
115       * @return The success value.
116       */
117      public T successE(final P1<String> err) {
118        return e.right().valueE(err);
119      }
120    
121      /**
122       * Returns the success value or fails with the given error message.
123       *
124       * @param err The error message to fail with.
125       * @return The success value.
126       */
127      public T successE(final String err) {
128        return e.right().valueE(p(err));
129      }
130    
131      /**
132       * Returns the success value or the given value.
133       *
134       * @param t The value to return if this is failure.
135       * @return The success value or the given value.
136       */
137      public T orSuccess(final P1<T> t) {
138        return e.right().orValue(t);
139      }
140    
141      /**
142       * Returns the success value or the given value.
143       *
144       * @param t The value to return if this is failure.
145       * @return The success value or the given value.
146       */
147      public T orSuccess(final T t) {
148        return e.right().orValue(p(t));
149      }
150    
151      /**
152       * The success value or the application of the given function to the failing value.
153       *
154       * @param f The function to execute on the failing value.
155       * @return The success value or the application of the given function to the failing value.
156       */
157      public T on(final F<E, T> f) {
158        return e.right().on(f);
159      }
160    
161      /**
162       * Executes a side-effect on the success value if there is one.
163       *
164       * @param f The side-effect to execute.
165       * @return The unit value.
166       */
167      public Unit foreach(final F<T, Unit> f) {
168        return e.right().foreach(f);
169      }
170    
171      /**
172       * Executes a side-effect on the success value if there is one.
173       *
174       * @param f The side-effect to execute.
175       */
176      public void foreach(final Effect<T> f) {
177        e.right().foreach(f);
178      }
179    
180      /**
181       * Maps the given function across the success side of this validation.
182       *
183       * @param f The function to map.
184       * @return A new validation with the function mapped.
185       */
186      @SuppressWarnings({"unchecked"})
187      public <A> Validation<E, A> map(final F<T, A> f) {
188        return isFail() ?
189            Validation.<E, A>fail(fail()) :
190            Validation.<E, A>success(f.f(success()));
191      }
192    
193      /**
194       * Binds the given function across this validation's success value if it has one.
195       *
196       * @param f The function to bind across this validation.
197       * @return A new validation value after binding.
198       */
199      @SuppressWarnings({"unchecked"})
200      public <A> Validation<E, A> bind(final F<T, Validation<E, A>> f) {
201        return isSuccess() ? f.f(success()) : Validation.<E, A>fail(fail());
202      }
203    
204      /**
205       * Anonymous bind through this validation.
206       *
207       * @param v The value to bind with.
208       * @return A validation after binding.
209       */
210      public <A> Validation<E, A> sequence(final Validation<E, A> v) {
211        return bind(fj.Function.<T, Validation<E, A>>constant(v));
212      }
213    
214      /**
215       * Returns <code>None</code> if this is a failure or if the given predicate <code>p</code> does not hold for the
216       * success value, otherwise, returns a success in <code>Some</code>.
217       *
218       * @param f The predicate function to test on this success value.
219       * @return <code>None</code> if this is a failure or if the given predicate <code>p</code> does not hold for the
220       *         success value, otherwise, returns a success in <code>Some</code>.
221       */
222      public <A> Option<Validation<A, T>> filter(final F<T, Boolean> f) {
223        return e.right().<A>filter(f).map(Validation.<A, T>validation());
224      }
225    
226      /**
227       * Function application on the success value.
228       *
229       * @param v The validation of the function to apply on the success value.
230       * @return The result of function application in validation.
231       */
232      public <A> Validation<E, A> apply(final Validation<E, F<T, A>> v) {
233        return v.bind(new F<F<T, A>, Validation<E, A>>() {
234          public Validation<E, A> f(final F<T, A> f) {
235            return map(f);
236          }
237        });
238      }
239    
240      /**
241       * Returns <code>true</code> if this is a failure or returns the result of the application of the given
242       * function to the success value.
243       *
244       * @param f The predicate function to test on this success value.
245       * @return <code>true</code> if this is a failure or returns the result of the application of the given
246       *         function to the success value.
247       */
248      public boolean forall(final F<T, Boolean> f) {
249        return e.right().forall(f);
250      }
251    
252      /**
253       * Returns <code>false</code> if this is a failure or returns the result of the application of the given
254       * function to the success value.
255       *
256       * @param f The predicate function to test on this success value.
257       * @return <code>false</code> if this is a failure or returns the result of the application of the given
258       *         function to the success value.
259       */
260      public boolean exists(final F<T, Boolean> f) {
261        return e.right().exists(f);
262      }
263    
264      /**
265       * Returns a single element list if this is a success value, otherwise an empty list.
266       *
267       * @return A single element list if this is a success value, otherwise an empty list.
268       */
269      public List<T> toList() {
270        return e.right().toList();
271      }
272    
273      /**
274       * Returns the success value in <code>Some</code> if there is one, otherwise <code>None</code>.
275       *
276       * @return The success value in <code>Some</code> if there is one, otherwise <code>None</code>.
277       */
278      public Option<T> toOption() {
279        return e.right().toOption();
280      }
281    
282      /**
283       * Returns a single element array if this is a success value, otherwise an empty list.
284       *
285       * @return A single element array if this is a success value, otherwise an empty list.
286       */
287      public Array<T> toArray() {
288        return e.right().toArray();
289      }
290    
291      /**
292       * Returns a single element stream if this is a success value, otherwise an empty list.
293       *
294       * @return A single element stream if this is a success value, otherwise an empty list.
295       */
296      public Stream<T> toStream() {
297        return e.right().toStream();
298      }
299    
300      /**
301       * Function application on the successful side of this validation, or accumulating the errors on the failing side
302       * using the given semigroup should one or more be encountered.
303       *
304       * @param s The semigroup to accumulate errors with if
305       * @param v The validating function to apply.
306       * @return A failing validation if this or the given validation failed (with errors accumulated if both) or a
307       *         succeeding validation if both succeeded.
308       */
309      @SuppressWarnings({"unchecked"})
310      public <A> Validation<E, A> accumapply(final Semigroup<E> s, final Validation<E, F<T, A>> v) {
311        return isFail() ?
312            Validation.<E, A>fail(v.isFail() ?
313                s.sum(v.fail(), fail()) :
314                fail()) :
315            v.isFail() ?
316                Validation.<E, A>fail(v.fail()) :
317                Validation.<E, A>success(v.success().f(success()));
318      }
319    
320      /**
321       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
322       * the given function if all succeeded and returns that value on the successful side.
323       *
324       * @param s  The semigroup to accumulate errors with if one or more validations fail.
325       * @param va The second validation to accumulate errors with if it failed.
326       * @param f  The function to apply if all validations have succeeded.
327       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
328       *         one or more failed.
329       */
330      public <A, B> Validation<E, B> accumulate(final Semigroup<E> s, final Validation<E, A> va, final F<T, F<A, B>> f) {
331        return va.accumapply(s, map(f));
332      }
333    
334      /**
335       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
336       * the given function if all succeeded and returns that value on the successful side.
337       *
338       * @param s  The semigroup to accumulate errors with if one or more validations fail.
339       * @param va The second validation to accumulate errors with if it failed.
340       * @param f  The function to apply if all validations have succeeded.
341       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
342       *         one or more failed.
343       */
344      public <A, B> Validation<E, B> accumulate(final Semigroup<E> s, final Validation<E, A> va, final F2<T, A, B> f) {
345        return va.accumapply(s, map(curry(f)));
346      }
347    
348      /**
349       * Accumulates errors anonymously.
350       *
351       * @param s  The semigroup to accumulate errors with if one or more validations fail.
352       * @param va The second validation to accumulate errors with if it failed.
353       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
354       *         <code>None</code>.
355       */
356      public <A> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va) {
357        return accumulate(s, va, new F2<T, A, Unit>() {
358          public Unit f(final T t, final A a) {
359            return unit();
360          }
361        }).f().toOption();
362      }
363    
364      /**
365       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
366       * the given function if all succeeded and returns that value on the successful side.
367       *
368       * @param s  The semigroup to accumulate errors with if one or more validations fail.
369       * @param va The second validation to accumulate errors with if it failed.
370       * @param vb The third validation to accumulate errors with if it failed.
371       * @param f  The function to apply if all validations have succeeded.
372       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
373       *         one or more failed.
374       */
375      public <A, B, C> Validation<E, C> accumulate(final Semigroup<E> s, final Validation<E, A> va,
376                                                   final Validation<E, B> vb, final F<T, F<A, F<B, C>>> f) {
377        return vb.accumapply(s, accumulate(s, va, f));
378      }
379    
380      /**
381       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
382       * the given function if all succeeded and returns that value on the successful side.
383       *
384       * @param s  The semigroup to accumulate errors with if one or more validations fail.
385       * @param va The second validation to accumulate errors with if it failed.
386       * @param vb The third validation to accumulate errors with if it failed.
387       * @param f  The function to apply if all validations have succeeded.
388       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
389       *         one or more failed.
390       */
391      public <A, B, C> Validation<E, C> accumulate(final Semigroup<E> s, final Validation<E, A> va,
392                                                   final Validation<E, B> vb, final F3<T, A, B, C> f) {
393        return vb.accumapply(s, accumulate(s, va, curry(f)));
394      }
395    
396      /**
397       * Accumulates errors anonymously.
398       *
399       * @param s  The semigroup to accumulate errors with if one or more validations fail.
400       * @param va The second validation to accumulate errors with if it failed.
401       * @param vb The third validation to accumulate errors with if it failed.
402       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
403       *         <code>None</code>.
404       */
405      public <A, B> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va, final Validation<E, B> vb) {
406        return accumulate(s, va, vb, new F3<T, A, B, Unit>() {
407          public Unit f(final T t, final A a, final B b) {
408            return unit();
409          }
410        }).f().toOption();
411      }
412    
413      /**
414       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
415       * the given function if all succeeded and returns that value on the successful side.
416       *
417       * @param s  The semigroup to accumulate errors with if one or more validations fail.
418       * @param va The second validation to accumulate errors with if it failed.
419       * @param vb The third validation to accumulate errors with if it failed.
420       * @param vc The fourth validation to accumulate errors with if it failed.
421       * @param f  The function to apply if all validations have succeeded.
422       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
423       *         one or more failed.
424       */
425      public <A, B, C, D> Validation<E, D> accumulate(final Semigroup<E> s, final Validation<E, A> va,
426                                                      final Validation<E, B> vb, final Validation<E, C> vc,
427                                                      final F<T, F<A, F<B, F<C, D>>>> f) {
428        return vc.accumapply(s, accumulate(s, va, vb, f));
429      }
430    
431      /**
432       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
433       * the given function if all succeeded and returns that value on the successful side.
434       *
435       * @param s  The semigroup to accumulate errors with if one or more validations fail.
436       * @param va The second validation to accumulate errors with if it failed.
437       * @param vb The third validation to accumulate errors with if it failed.
438       * @param vc The fourth validation to accumulate errors with if it failed.
439       * @param f  The function to apply if all validations have succeeded.
440       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
441       *         one or more failed.
442       */
443      public <A, B, C, D> Validation<E, D> accumulate(final Semigroup<E> s, final Validation<E, A> va,
444                                                      final Validation<E, B> vb, final Validation<E, C> vc,
445                                                      final F4<T, A, B, C, D> f) {
446        return vc.accumapply(s, accumulate(s, va, vb, curry(f)));
447      }
448    
449      /**
450       * Accumulates errors anonymously.
451       *
452       * @param s  The semigroup to accumulate errors with if one or more validations fail.
453       * @param va The second validation to accumulate errors with if it failed.
454       * @param vb The third validation to accumulate errors with if it failed.
455       * @param vc The fourth validation to accumulate errors with if it failed.
456       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
457       *         <code>None</code>.
458       */
459      public <A, B, C> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va, final Validation<E, B> vb,
460                                            final Validation<E, C> vc) {
461        return accumulate(s, va, vb, vc, new F4<T, A, B, C, Unit>() {
462          public Unit f(final T t, final A a, final B b, final C c) {
463            return unit();
464          }
465        }).f().toOption();
466      }
467    
468      /**
469       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
470       * the given function if all succeeded and returns that value on the successful side.
471       *
472       * @param s  The semigroup to accumulate errors with if one or more validations fail.
473       * @param va The second validation to accumulate errors with if it failed.
474       * @param vb The third validation to accumulate errors with if it failed.
475       * @param vc The fourth validation to accumulate errors with if it failed.
476       * @param vd The fifth validation to accumulate errors with if it failed.
477       * @param f  The function to apply if all validations have succeeded.
478       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
479       *         one or more failed.
480       */
481      public <A, B, C, D, E$> Validation<E, E$> accumulate(final Semigroup<E> s, final Validation<E, A> va,
482                                                           final Validation<E, B> vb, final Validation<E, C> vc,
483                                                           final Validation<E, D> vd,
484                                                           final F<T, F<A, F<B, F<C, F<D, E$>>>>> f) {
485        return vd.accumapply(s, accumulate(s, va, vb, vc, f));
486      }
487    
488      /**
489       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
490       * the given function if all succeeded and returns that value on the successful side.
491       *
492       * @param s  The semigroup to accumulate errors with if one or more validations fail.
493       * @param va The second validation to accumulate errors with if it failed.
494       * @param vb The third validation to accumulate errors with if it failed.
495       * @param vc The fourth validation to accumulate errors with if it failed.
496       * @param vd The fifth validation to accumulate errors with if it failed.
497       * @param f  The function to apply if all validations have succeeded.
498       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
499       *         one or more failed.
500       */
501      public <A, B, C, D, E$> Validation<E, E$> accumulate(final Semigroup<E> s, final Validation<E, A> va,
502                                                           final Validation<E, B> vb, final Validation<E, C> vc,
503                                                           final Validation<E, D> vd, final F5<T, A, B, C, D, E$> f) {
504        return vd.accumapply(s, accumulate(s, va, vb, vc, curry(f)));
505      }
506    
507      /**
508       * Accumulates errors anonymously.
509       *
510       * @param s  The semigroup to accumulate errors with if one or more validations fail.
511       * @param va The second validation to accumulate errors with if it failed.
512       * @param vb The third validation to accumulate errors with if it failed.
513       * @param vc The fourth validation to accumulate errors with if it failed.
514       * @param vd The fifth validation to accumulate errors with if it failed.
515       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
516       *         <code>None</code>.
517       */
518      public <A, B, C, D> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va, final Validation<E, B> vb,
519                                               final Validation<E, C> vc, final Validation<E, D> vd) {
520        return accumulate(s, va, vb, vc, vd, new F5<T, A, B, C, D, Unit>() {
521          public Unit f(final T t, final A a, final B b, final C c, final D d) {
522            return unit();
523          }
524        }).f().toOption();
525      }
526    
527      /**
528       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
529       * the given function if all succeeded and returns that value on the successful side.
530       *
531       * @param s  The semigroup to accumulate errors with if one or more validations fail.
532       * @param va The second validation to accumulate errors with if it failed.
533       * @param vb The third validation to accumulate errors with if it failed.
534       * @param vc The fourth validation to accumulate errors with if it failed.
535       * @param vd The fifth validation to accumulate errors with if it failed.
536       * @param ve The sixth validation to accumulate errors with if it failed.
537       * @param f  The function to apply if all validations have succeeded.
538       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
539       *         one or more failed.
540       */
541      public <A, B, C, D, E$, F$> Validation<E, F$> accumulate(final Semigroup<E> s, final Validation<E, A> va,
542                                                               final Validation<E, B> vb, final Validation<E, C> vc,
543                                                               final Validation<E, D> vd, final Validation<E, E$> ve,
544                                                               final F<T, F<A, F<B, F<C, F<D, F<E$, F$>>>>>> f) {
545        return ve.accumapply(s, accumulate(s, va, vb, vc, vd, f));
546      }
547    
548      /**
549       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
550       * the given function if all succeeded and returns that value on the successful side.
551       *
552       * @param s  The semigroup to accumulate errors with if one or more validations fail.
553       * @param va The second validation to accumulate errors with if it failed.
554       * @param vb The third validation to accumulate errors with if it failed.
555       * @param vc The fourth validation to accumulate errors with if it failed.
556       * @param vd The fifth validation to accumulate errors with if it failed.
557       * @param ve The sixth validation to accumulate errors with if it failed.
558       * @param f  The function to apply if all validations have succeeded.
559       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
560       *         one or more failed.
561       */
562      public <A, B, C, D, E$, F$> Validation<E, F$> accumulate(final Semigroup<E> s, final Validation<E, A> va,
563                                                               final Validation<E, B> vb, final Validation<E, C> vc,
564                                                               final Validation<E, D> vd, final Validation<E, E$> ve,
565                                                               final F6<T, A, B, C, D, E$, F$> f) {
566        return ve.accumapply(s, accumulate(s, va, vb, vc, vd, curry(f)));
567      }
568    
569      /**
570       * Accumulates errors anonymously.
571       *
572       * @param s  The semigroup to accumulate errors with if one or more validations fail.
573       * @param va The second validation to accumulate errors with if it failed.
574       * @param vb The third validation to accumulate errors with if it failed.
575       * @param vc The fourth validation to accumulate errors with if it failed.
576       * @param vd The fifth validation to accumulate errors with if it failed.
577       * @param ve The sixth validation to accumulate errors with if it failed.
578       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
579       *         <code>None</code>.
580       */
581      public <A, B, C, D, E$> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va,
582                                                   final Validation<E, B> vb, final Validation<E, C> vc,
583                                                   final Validation<E, D> vd, final Validation<E, E$> ve) {
584        return accumulate(s, va, vb, vc, vd, ve, new F6<T, A, B, C, D, E$, Unit>() {
585          public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e) {
586            return unit();
587          }
588        }).f().toOption();
589      }
590    
591      /**
592       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
593       * the given function if all succeeded and returns that value on the successful side.
594       *
595       * @param s  The semigroup to accumulate errors with if one or more validations fail.
596       * @param va The second validation to accumulate errors with if it failed.
597       * @param vb The third validation to accumulate errors with if it failed.
598       * @param vc The fourth validation to accumulate errors with if it failed.
599       * @param vd The fifth validation to accumulate errors with if it failed.
600       * @param ve The sixth validation to accumulate errors with if it failed.
601       * @param vf The seventh validation to accumulate errors with if it failed.
602       * @param f  The function to apply if all validations have succeeded.
603       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
604       *         one or more failed.
605       */
606      public <A, B, C, D, E$, F$, G> Validation<E, G> accumulate(final Semigroup<E> s, final Validation<E, A> va,
607                                                                 final Validation<E, B> vb, final Validation<E, C> vc,
608                                                                 final Validation<E, D> vd, final Validation<E, E$> ve,
609                                                                 final Validation<E, F$> vf,
610                                                                 final F<T, F<A, F<B, F<C, F<D, F<E$, F<F$, G>>>>>>> f) {
611        return vf.accumapply(s, accumulate(s, va, vb, vc, vd, ve, f));
612      }
613    
614      /**
615       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
616       * the given function if all succeeded and returns that value on the successful side.
617       *
618       * @param s  The semigroup to accumulate errors with if one or more validations fail.
619       * @param va The second validation to accumulate errors with if it failed.
620       * @param vb The third validation to accumulate errors with if it failed.
621       * @param vc The fourth validation to accumulate errors with if it failed.
622       * @param vd The fifth validation to accumulate errors with if it failed.
623       * @param ve The sixth validation to accumulate errors with if it failed.
624       * @param vf The seventh validation to accumulate errors with if it failed.
625       * @param f  The function to apply if all validations have succeeded.
626       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
627       *         one or more failed.
628       */
629      public <A, B, C, D, E$, F$, G> Validation<E, G> accumulate(final Semigroup<E> s, final Validation<E, A> va,
630                                                                 final Validation<E, B> vb, final Validation<E, C> vc,
631                                                                 final Validation<E, D> vd, final Validation<E, E$> ve,
632                                                                 final Validation<E, F$> vf,
633                                                                 final F7<T, A, B, C, D, E$, F$, G> f) {
634        return vf.accumapply(s, accumulate(s, va, vb, vc, vd, ve, curry(f)));
635      }
636    
637      /**
638       * Accumulates errors anonymously.
639       *
640       * @param s  The semigroup to accumulate errors with if one or more validations fail.
641       * @param va The second validation to accumulate errors with if it failed.
642       * @param vb The third validation to accumulate errors with if it failed.
643       * @param vc The fourth validation to accumulate errors with if it failed.
644       * @param vd The fifth validation to accumulate errors with if it failed.
645       * @param ve The sixth validation to accumulate errors with if it failed.
646       * @param vf The seventh validation to accumulate errors with if it failed.
647       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
648       *         <code>None</code>.
649       */
650      public <A, B, C, D, E$, F$> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va,
651                                                       final Validation<E, B> vb, final Validation<E, C> vc,
652                                                       final Validation<E, D> vd, final Validation<E, E$> ve,
653                                                       final Validation<E, F$> vf) {
654        return accumulate(s, va, vb, vc, vd, ve, vf, new F7<T, A, B, C, D, E$, F$, Unit>() {
655          public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e, final F$ f) {
656            return unit();
657          }
658        }).f().toOption();
659      }
660    
661      /**
662       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
663       * the given function if all succeeded and returns that value on the successful side.
664       *
665       * @param s  The semigroup to accumulate errors with if one or more validations fail.
666       * @param va The second validation to accumulate errors with if it failed.
667       * @param vb The third validation to accumulate errors with if it failed.
668       * @param vc The fourth validation to accumulate errors with if it failed.
669       * @param vd The fifth validation to accumulate errors with if it failed.
670       * @param ve The sixth validation to accumulate errors with if it failed.
671       * @param vf The seventh validation to accumulate errors with if it failed.
672       * @param vg The eighth validation to accumulate errors with if it failed.
673       * @param f  The function to apply if all validations have succeeded.
674       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
675       *         one or more failed.
676       */
677      public <A, B, C, D, E$, F$, G, H> Validation<E, H> accumulate(final Semigroup<E> s, final Validation<E, A> va,
678                                                                    final Validation<E, B> vb, final Validation<E, C> vc,
679                                                                    final Validation<E, D> vd, final Validation<E, E$> ve,
680                                                                    final Validation<E, F$> vf, final Validation<E, G> vg,
681                                                                    final F<T, F<A, F<B, F<C, F<D, F<E$, F<F$, F<G, H>>>>>>>> f) {
682        return vg.accumapply(s, accumulate(s, va, vb, vc, vd, ve, vf, f));
683      }
684    
685      /**
686       * Accumulates errors on the failing side of this or any given validation if one or more are encountered, or applies
687       * the given function if all succeeded and returns that value on the successful side.
688       *
689       * @param s  The semigroup to accumulate errors with if one or more validations fail.
690       * @param va The second validation to accumulate errors with if it failed.
691       * @param vb The third validation to accumulate errors with if it failed.
692       * @param vc The fourth validation to accumulate errors with if it failed.
693       * @param vd The fifth validation to accumulate errors with if it failed.
694       * @param ve The sixth validation to accumulate errors with if it failed.
695       * @param vf The seventh validation to accumulate errors with if it failed.
696       * @param vg The eighth validation to accumulate errors with if it failed.
697       * @param f  The function to apply if all validations have succeeded.
698       * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if
699       *         one or more failed.
700       */
701      public <A, B, C, D, E$, F$, G, H> Validation<E, H> accumulate(final Semigroup<E> s, final Validation<E, A> va,
702                                                                    final Validation<E, B> vb, final Validation<E, C> vc,
703                                                                    final Validation<E, D> vd, final Validation<E, E$> ve,
704                                                                    final Validation<E, F$> vf, final Validation<E, G> vg,
705                                                                    final F8<T, A, B, C, D, E$, F$, G, H> f) {
706        return vg.accumapply(s, accumulate(s, va, vb, vc, vd, ve, vf, curry(f)));
707      }
708    
709      /**
710       * Accumulates errors anonymously.
711       *
712       * @param s  The semigroup to accumulate errors with if one or more validations fail.
713       * @param va The second validation to accumulate errors with if it failed.
714       * @param vb The third validation to accumulate errors with if it failed.
715       * @param vc The fourth validation to accumulate errors with if it failed.
716       * @param vd The fifth validation to accumulate errors with if it failed.
717       * @param ve The sixth validation to accumulate errors with if it failed.
718       * @param vf The seventh validation to accumulate errors with if it failed.
719       * @param vg The eighth validation to accumulate errors with if it failed.
720       * @return A <code>Some</code> if one or more validations failed (accumulated with the semigroup), otherwise,
721       *         <code>None</code>.
722       */
723      public <A, B, C, D, E$, F$, G> Option<E> accumulate(final Semigroup<E> s, final Validation<E, A> va,
724                                                          final Validation<E, B> vb, final Validation<E, C> vc,
725                                                          final Validation<E, D> vd, final Validation<E, E$> ve,
726                                                          final Validation<E, F$> vf, final Validation<E, G> vg) {
727        return accumulate(s, va, vb, vc, vd, ve, vf, vg, new F8<T, A, B, C, D, E$, F$, G, Unit>() {
728          public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e, final F$ f, final G g) {
729            return unit();
730          }
731        }).f().toOption();
732      }
733    
734      /**
735       * Returns an iterator for this validation. This method exists to permit the use in a <code>for</code>-each loop.
736       *
737       * @return A iterator for this validation.
738       */
739      public Iterator<T> iterator() {
740        return toEither().right().iterator();
741      }
742    
743      /**
744       * A failing projection of a validation.
745       */
746      public final class FailProjection<E, T> implements Iterable<E> {
747        private final Validation<E, T> v;
748    
749        private FailProjection(final Validation<E, T> v) {
750          this.v = v;
751        }
752    
753        /**
754         * Returns the underlying validation.
755         *
756         * @return The underlying validation.
757         */
758        public Validation<E, T> validation() {
759          return v;
760        }
761    
762        /**
763         * Returns the failing value or fails with the given error message.
764         *
765         * @param err The error message to fail with.
766         * @return The failing value.
767         */
768        public E failE(final P1<String> err) {
769          return v.toEither().left().valueE(err);
770        }
771    
772        /**
773         * Returns the failing value or fails with the given error message.
774         *
775         * @param err The error message to fail with.
776         * @return The failing value.
777         */
778        public E failE(final String err) {
779          return failE(p(err));
780        }
781    
782        /**
783         * Returns the failing value or the given value.
784         *
785         * @param e The value to return if this is success.
786         * @return The failing value or the given value.
787         */
788        public E orFail(final P1<E> e) {
789          return v.toEither().left().orValue(e);
790        }
791    
792        /**
793         * Returns the failing value or the given value.
794         *
795         * @param e The value to return if this is success.
796         * @return The failing value or the given value.
797         */
798        public E orFail(final E e) {
799          return orFail(p(e));
800        }
801    
802        /**
803         * The failing value or the application of the given function to the success value.
804         *
805         * @param f The function to execute on the success value.
806         * @return The failing value or the application of the given function to the success value.
807         */
808        public E on(final F<T, E> f) {
809          return v.toEither().left().on(f);
810        }
811    
812        /**
813         * Executes a side-effect on the failing value if there is one.
814         *
815         * @param f The side-effect to execute.
816         * @return The unit value.
817         */
818        public Unit foreach(final F<E, Unit> f) {
819          return v.toEither().left().foreach(f);
820        }
821    
822        /**
823         * Executes a side-effect on the failing value if there is one.
824         *
825         * @param f The side-effect to execute.
826         */
827        public void foreach(final Effect<E> f) {
828          v.toEither().left().foreach(f);
829        }
830    
831        /**
832         * Maps the given function across the failing side of this validation.
833         *
834         * @param f The function to map.
835         * @return A new validation with the function mapped.
836         */
837        public <A> Validation<A, T> map(final F<E, A> f) {
838          return Validation.validation(v.toEither().left().map(f));
839        }
840    
841        /**
842         * Binds the given function across this validation's failing value if it has one.
843         *
844         * @param f The function to bind across this validation.
845         * @return A new validation value after binding.
846         */
847        public <A> Validation<A, T> bind(final F<E, Validation<A, T>> f) {
848          return v.isFail() ? f.f(v.fail()) : Validation.<A, T>success(v.success());
849        }
850    
851        /**
852         * Performs a bind across the validation, but ignores the element value in the function.
853         *
854         * @param v The validation value to apply in the final join.
855         * @return A new validation value after the final join.
856         */
857        public <A> Validation<A, T> sequence(final Validation<A, T> v) {
858          return bind(new F<E, Validation<A, T>>() {
859            public Validation<A, T> f(final E e) {
860              return v;
861            }
862          });
863        }
864    
865        /**
866         * Returns <code>None</code> if this is a success or if the given predicate <code>p</code> does not hold for the
867         * failing value, otherwise, returns a fail in <code>Some</code>.
868         *
869         * @param f The predicate function to test on this failing value.
870         * @return <code>None</code> if this is a success or if the given predicate <code>p</code> does not hold for the
871         *         failing value, otherwise, returns a fail in <code>Some</code>.
872         */
873        public <A> Option<Validation<E, A>> filter(final F<E, Boolean> f) {
874          return v.toEither().left().<A>filter(f).map(Validation.<E, A>validation());
875        }
876    
877        /**
878         * Function application on the failing value.
879         *
880         * @param v The validation of the function to apply on the failing value.
881         * @return The result of function application in validation.
882         */
883        public <A> Validation<A, T> apply(final Validation<F<E, A>, T> v) {
884          return v.f().bind(new F<F<E, A>, Validation<A, T>>() {
885            public Validation<A, T> f(final F<E, A> f) {
886              return map(f);
887            }
888          });
889        }
890    
891        /**
892         * Returns <code>true</code> if this is a success or returns the result of the application of the given
893         * function to the failing value.
894         *
895         * @param f The predicate function to test on this failing value.
896         * @return <code>true</code> if this is a success or returns the result of the application of the given
897         *         function to the failing value.
898         */
899        public boolean forall(final F<E, Boolean> f) {
900          return v.toEither().left().forall(f);
901        }
902    
903        /**
904         * Returns <code>false</code> if this is a success or returns the result of the application of the given
905         * function to the failing value.
906         *
907         * @param f The predicate function to test on this failing value.
908         * @return <code>false</code> if this is a success or returns the result of the application of the given
909         *         function to the failing value.
910         */
911        public boolean exists(final F<E, Boolean> f) {
912          return v.toEither().left().exists(f);
913        }
914    
915        /**
916         * Returns a single element list if this is a failing value, otherwise an empty list.
917         *
918         * @return A single element list if this is a failing value, otherwise an empty list.
919         */
920        public List<E> toList() {
921          return v.toEither().left().toList();
922        }
923    
924        /**
925         * Returns the failing value in <code>Some</code> if there is one, otherwise <code>None</code>.
926         *
927         * @return The failing value in <code>Some</code> if there is one, otherwise <code>None</code>.
928         */
929        public Option<E> toOption() {
930          return v.toEither().left().toOption();
931        }
932    
933        /**
934         * Returns a single element array if this is a failing value, otherwise an empty list.
935         *
936         * @return A single element array if this is a failing value, otherwise an empty list.
937         */
938        public Array<E> toArray() {
939          return v.toEither().left().toArray();
940        }
941    
942        /**
943         * Returns a single element stream if this is a failing value, otherwise an empty list.
944         *
945         * @return A single element stream if this is a failing value, otherwise an empty list.
946         */
947        public Stream<E> toStream() {
948          return v.toEither().left().toStream();
949        }
950    
951        /**
952         * Returns an iterator for this projection. This method exists to permit the use in a <code>for</code>-each loop.
953         *
954         * @return A iterator for this projection.
955         */
956        public Iterator<E> iterator() {
957          return v.toEither().left().iterator();
958        }
959      }
960    
961      /**
962       * Puts this validation's failing value in a non-empty list if there is one.
963       *
964       * @return A validation with its failing value in a non-empty list if there is one.
965       */
966      @SuppressWarnings({"unchecked"})
967      public Validation<NonEmptyList<E>, T> nel() {
968        return isSuccess() ?
969            Validation.<NonEmptyList<E>, T>success(success()) :
970            Validation.<NonEmptyList<E>, T>fail(NonEmptyList.nel(fail()));
971      }
972    
973      /**
974       * Construct a validation using the given either value.
975       *
976       * @param e The either value to construct a validation with.
977       * @return A validation using the given either value.
978       */
979      public static <E, T> Validation<E, T> validation(final Either<E, T> e) {
980        return new Validation<E, T>(e);
981      }
982    
983      /**
984       * Returns a function that constructs a validation with an either.
985       *
986       * @return A function that constructs a validation with an either.
987       */
988      public static <E, T> F<Either<E, T>, Validation<E, T>> validation() {
989        return new F<Either<E, T>, Validation<E, T>>() {
990          public Validation<E, T> f(final Either<E, T> e) {
991            return validation(e);
992          }
993        };
994      }
995    
996      /**
997       * Returns a function that constructs an either with a validation.
998       *
999       * @return A function that constructs an either with a validation.
1000       */
1001      public static <E, T> F<Validation<E, T>, Either<E, T>> either() {
1002        return new F<Validation<E, T>, Either<E, T>>() {
1003          public Either<E, T> f(final Validation<E, T> v) {
1004            return v.toEither();
1005          }
1006        };
1007      }
1008    
1009      /**
1010       * Returns a succeeding validation containing the given value.
1011       *
1012       * @param t The value to use in the succeeding validation.
1013       * @return A succeeding validation containing the given value.
1014       */
1015      public static <E, T> Validation<E, T> success(final T t) {
1016        return validation(Either.<E, T>right(t));
1017      }
1018    
1019      /**
1020       * Returns a failing validation containing the given value.
1021       *
1022       * @param e The value to use in the failing validation.
1023       * @return A failing validation containing the given value.
1024       */
1025      public static <E, T> Validation<E, T> fail(final E e) {
1026        return validation(Either.<E, T>left(e));
1027      }
1028    
1029      /**
1030       * Returns a failing validation containing a non-empty list that contains the given value.
1031       *
1032       * @param e The value to use in a non-empty list for the failing validation.
1033       * @return A failing validation containing a non-empty list that contains the given value.
1034       */
1035      public static <E, T> Validation<NonEmptyList<E>, T> failNEL(final E e) {
1036        return fail(NonEmptyList.nel(e));
1037      }
1038    
1039      /**
1040       * Returns a validation based on a boolean condition. If the condition is <code>true</code>, the validation succeeds,
1041       * otherwise it fails.
1042       *
1043       * @param c The condition to base the returned validation on.
1044       * @param e The failing value to use if the condition is <code>false</code>.
1045       * @param t The succeeding value to use if the condition is <code>true</code>.
1046       * @return A validation based on a boolean condition.
1047       */
1048      public static <E, T> Validation<E, T> condition(final boolean c, final E e, final T t) {
1049        return c ? Validation.<E, T>success(t) : Validation.<E, T>fail(e);
1050      }
1051    
1052      /**
1053       * Parses the given string into a byte.
1054       *
1055       * @param s The string to parse.
1056       * @return A successfully parse byte or a failing exception.
1057       */
1058      public static Validation<NumberFormatException, Byte> parseByte(final String s) {
1059        try {
1060          return success(Byte.parseByte(s));
1061        } catch (NumberFormatException e) {
1062          return fail(e);
1063        }
1064      }
1065    
1066      /**
1067       * Parses the given string into a double.
1068       *
1069       * @param s The string to parse.
1070       * @return A successfully parse double or a failing exception.
1071       */
1072      public static Validation<NumberFormatException, Double> parseDouble(final String s) {
1073        try {
1074          return success(Double.parseDouble(s));
1075        } catch (NumberFormatException e) {
1076          return fail(e);
1077        }
1078      }
1079    
1080      /**
1081       * Parses the given string into a float.
1082       *
1083       * @param s The string to parse.
1084       * @return A successfully parse float or a failing exception.
1085       */
1086      public static Validation<NumberFormatException, Float> parseFloat(final String s) {
1087        try {
1088          return success(Float.parseFloat(s));
1089        } catch (NumberFormatException e) {
1090          return fail(e);
1091        }
1092      }
1093    
1094      /**
1095       * Parses the given string into a integer.
1096       *
1097       * @param s The string to parse.
1098       * @return A successfully parse integer or a failing exception.
1099       */
1100      public static Validation<NumberFormatException, Integer> parseInt(final String s) {
1101        try {
1102          return success(Integer.parseInt(s));
1103        } catch (NumberFormatException e) {
1104          return fail(e);
1105        }
1106      }
1107    
1108      /**
1109       * Parses the given string into a long.
1110       *
1111       * @param s The string to parse.
1112       * @return A successfully parse long or a failing exception.
1113       */
1114      public static Validation<NumberFormatException, Long> parseLong(final String s) {
1115        try {
1116          return success(Long.parseLong(s));
1117        } catch (NumberFormatException e) {
1118          return fail(e);
1119        }
1120      }
1121    
1122      /**
1123       * Parses the given string into a short.
1124       *
1125       * @param s The string to parse.
1126       * @return A successfully parse short or a failing exception.
1127       */
1128      public static Validation<NumberFormatException, Short> parseShort(final String s) {
1129        try {
1130          return success(Short.parseShort(s));
1131        } catch (NumberFormatException e) {
1132          return fail(e);
1133        }
1134      }
1135    }