Functional Java 2.9

Patient: I have 6 potentially failing methods (a, b, c, d, e, f) and if one of those fails, I want to cease execution and return that failure, otherwise continue execution.

Doctor: What do they return if they succeed?

Patient: Nothing, they side-effect

Doctor: eek! OK, let’s see what we can do? What happens after you’ve completed this computation?

Patient: Well, it gets a bit hairier you see. Then I have 3 more potentially failing computations (g, h, i) and if any of those fail (or the original failed), then I also want to fail, however, I want to keep the errors in these last three computations.

Doctor: So let’s get this right, you perform all of the latter three computations regardless of their outcome and you only succeed if all nine computations succeed and you fail otherwise?

Patient: Yes, that’s right and…

Doctor: And for whatever silly reason, you’re using Java.

Patient: cowers; er yeah.

Doctor: Well, I’ve told you about that, haven’t I?

Patient: cowers more; yes you have but…

Doctor: So, if any of the first six computations fail, then you check the latter three for failures as well. These latter three are side-effecting, void return type, as well aren’t they?

Patient: Yes…

Doctor: If the first six succeed, you perform the latter three computations anyway, accumulating potential failures.

Patient: Right, exactly

Doctor: And just as an interesting observation, you will have at most, four errors and possibly none in the event of all nine succeeding.

Patient: Umm yeah, I hadn’t thought of it that way.

Doctor: smiles

  Validation<Throwable, Unit> a;
  Validation<Throwable, Unit> b;
  Validation<Throwable, Unit> c;
  Validation<Throwable, Unit> d;
  Validation<Throwable, Unit> e;
  Validation<Throwable, Unit> f;
  ////
  Validation<Throwable, Unit> g;
  Validation<Throwable, Unit> h;
  Validation<Throwable, Unit> i;
 
  Validation<Throwable, Unit> first() {
    return a.sequence(b).
            sequence(c).
            sequence(d).
            sequence(e).
            sequence(f);
  }
 
  Option<NonEmptyList<Throwable>> second() {
    return first().nel().accumulate(Semigroup.<Throwable>nonEmptyListSemigroup(),
            g.nel(),
            h.nel(),
            i.nel());
  }

Doctor: Now, this is the best that Java can do at solving this very popular request of yours, but come and see me when you’re ready to upgrade your tools…

Patient: Thanks Doc! I will!

Doctor: outward smile, inward scepticism; In the meantime, I will prescribe you with Functional Java 2.9 which is only going to work if you exercise at least some amount of intellectual discipline. You will need it for the solution above.

Doctor: On your way then.

Update: Functional Java 2.10 includes Validation.sequence.

2 Responses to “Functional Java 2.9”

  1. Daniel Jimenez Says:

    Interesting.

    Hmm, sequence looks familiar. Doesn’t seem to be defined on Validation, though. Validation is isomorphic to Either, Either has sequenceLeft/Right, taking a list of Either to an Either of List. Anything else? Yes, Option, list of Option to Option of list.

    But wait, Option has sequence taking an Option to an Option. Hold on, performs a bind, ignores ignores the element value … Oh, sequence (>>; as if I understood that :-))!

    What’s sequence on Validation? It must return the failure of its argument, or it passes on its right (success) side, Unit in this example. Is that right?

  2. tmorris Says:

    Oops, yeah Validation.sequence didn’t quite make it into 2.9. It is defined in trunk. Validation.sequence is an anonymous bind function. That is, instead of binding with a function λt.v where the value t is ignored, instead just pass v. It is similar in this way to Haskell’s >> function.

    We ignore the ‘t’ value because it is the Unit value (i.e. Unit is inhabited once). Then, accumulate also ignores this possible unit value (it doesn’t have to — there are overloads) while keeping any Throwable values using the given Semigroup (forall A. A -> A -> A). This Semigroup is the NonEmptyList implementation, so the errors are just prepended.

    By the end, you get either a NonEmptyList<Throwable>, which contains one or more errors, or you get None indicating that all nine side-effects executed successfully.

    Sorry about the little lie.

Leave a Reply