Lazy Error Handling in Java, Part 1: The Thrower Functor

How many try/catch blocks have you written in your day? Hundreds? Thousands? How many of the catch blocks look exactly the same? Is try/catch synonymous with copy/paste? Well, you may have written your last catch block. Follow me.

Let’s say that you’re coding in Java, and you want to call some code that might throw Exceptions, but you don’t want to be bothered with catching or throwing those exceptions in your code. Or you may want to call some existing code that doesn’t handle exceptions, passing it something that has methods which may throw exceptions. This can get ugly really fast, and you may end up with “throws Exception” declarations in places where you don’t want them, or try/catch blocks where you’re not sure whether to log the error or throw an unchecked exception, or what.

But, despair not. From very simple ingredients, we can conjure up powerful functional-style error handling to save the day. The first ingredient is a generic interface that declares, in its type expression, the exception thrown by its method:


  public interface Thrower<A, E extends Throwable>
   {public A extract() throws E;}
 

What we’re saying here is that there’s some operation preformed by extract() that returns an A and might throw an E. But the operation won’t take place (and won’t throw anything) until extract() is actually called.

What is such a thing useful for? Well, you could implement this interface, take parameters in a constructor, and perform some calculation in extract(). For example, reading a file and possibly throwing an IOException. But that’s a naive view of what generic interfaces are for. Thrower has higher aspirations than that. It’s not just an interface. It’s a functor. Observe:

  
  public static <A,B,E extends Throwable> F<Thrower<A,E>, Thrower<B,E>> fmap
    (final F<A,B> f)
    {return new F<Thrower<A,E>, Thrower<B,E>>()
      {public Thrower<B, E> f(final Thrower<A, E> a)
        {return new Thrower<B,E>()
          {public B extract() throws E
            {return f.f(a.extract());}};}};}
 

OK, so this is a static method on which class? It doesn’t matter, let’s say we put it in a utility class called Throwers (remembering to make it final and its constructor private). Just look at the type signature for now. The interface F<A,B> is from Functional Java, and it’s just an interface with one method B f(A a). So what fmap does is take a function from A to B, and return a function from Thrower<A,E> to Thrower<B,E>. In other words: fmap promotes the function f so that it works with computation that may throw checked errors, without f having been written to handle errors.

The implementation should be self-explanatory, albeit verbose (this is Java, after all). We construct an anonymous function to return, implementing its only method, which returns a new thrower which in turn yields the result of applying the function f to the contents extracted from the original thrower. It sounds a lot more complicated than it looks, so just read the code. All we’re doing is taking the A from a Thrower, turning it into a B, and wrapping that in another Thrower. If taking the A from the Thrower fails with an exception, we’ll carry that exception into the new Thrower.

The important thing to note here is that nothing actually happens until you call extract() on the resulting Thrower. Values of types F and Thrower are data structures that represent a computation to be carried out in the future. Anybody can pass Throwers around, but only a try/catch block, or a method that throws a Throwable of the right type may actually call extract() on it to run its computation and get its value. Java’s type system ensures that you can’t go wrong (although, as for unchecked exceptions, you’re on your own).

A simple example is in order. Just to illustrate the point, not to do anything very useful. This program reuses a function designed to operate on strings, so that it operates on operations that result in strings but might throw exceptions. The exception handling is done somewhere else, in ErrorHandler, outside of the main program, in an error handling library function called extractFrom, which we assume knows the right thing to do. Note that the main program has no try/catch block at all.

  
  public class Foo
   {public static void main (String[] args)
     {Thrower<String,IOException> readLn = new Thrower<String,IOException>()
       {public String extract() throws IOException
         {return new BufferedReader(new InputStreamReader(System.in)).readLine();}};
      System.out.println(ErrorHandler.extractFrom(Throwers.fmap(length).f(readLn)));}

    // A first-class function to get a String's length.
    public static F<String,Integer> length = new F<String,Integer>()
     {public Integer f(final String s)
       {return s.length();}};}
 

That’s right. You don’t have to handle exceptions at all in your code, even though you’re performing actions that throw exceptions. You just pass the buck to somebody who knows how to handle exceptions. It’s like outsourcing without the funny accents. OK, so you’re not really performing any IO actions, at least not syntactically speaking. ErrorHandler is doing that for you as well, since it’s the one calling extract() on the Thrower. This doesn’t make a difference to the compiled program except that the execution stack (and hence the stack trace, should things go terribly wrong) will look a bit different. If this makes you uncomfortable, here’s your hat and there’s the door. If you’ve ever used “Inversion of Control”, then this should be nothing new. In fact, in real life, you may want to inject something like ErrorHandler as a dependency, using Guice, or Spring, or something similar.

So there you go. That’s lazy error handling in Java, in a nutshell. But there’s more to come, as Thrower has higher aspirations still. It’s not just a functor. It’s a monad. We’ll talk about that in the next post.

24 thoughts on “Lazy Error Handling in Java, Part 1: The Thrower Functor

  1. In the 3rd Codeblock:
    return new BufferedReader(new InputStreamReader(System.in)).readln();
    should be
    return new BufferedReader(new InputStreamReader(System.in)).readLine ();
    shouldn’t it?

  2. Great blog! I’ve been trying to think of a good way to introduce a functional style in our code for ages, but have always been brought short in my efforts because of checked exceptions. This looks like just about the best solution I have seen, thank you so much!

  3. you, sir or madam, are a wonderful tonic against the regular java code which all too painfully predominates in our world. hearty thanks for kicking my brain around like that.

  4. Hello,
    I am just starting learning functional java, and i started reading this blog.

    I tried your example, but i get an error, which i dont really understand..

    When, in my main method i do the following:

    Throwers.fmap(length).f(readLn)))

    i get a compilation error, because f is expecting a (specifically), and readLn is of type

    Now i understand that E extends Throwable should cover that ground, but it doesnt..

    I tried looking harder, and i realized, that when we call fmap, we give it the length function, which has A defined to be String, but i guess since it doesnt define E at all, the compiler assumes it is a plain Throwable..

    What do i not get ??..

    I am using java 6.18, and tried java 5 too, but that couldnt be the problem since this post is from 2008..

    please help :)

    Shlomi

  5. ohh no.. the comment system removed all the generics from my post :(

    ill try again, this time with the code tag.. (sorry for the mess…)

    When, in my main method i do the following:

    Throwers.fmap(length).f(readLn)))

    i get a compilation error, because f is expecting a (specifically), and readLn is of type

    Now i understand that E extends Throwable should cover that ground, but it doesnt..

    I tried looking harder, and i realized, that when we call fmap, we give it the length function, which has A defined to be String, but i guess since it doesnt define E at all, the compiler assumes it is a plain Throwable..

    • ok. doesnt work. now i feel really dumb. and i used my real name too. hehe again.. this time ill use ‘[‘ and ‘]’ instead..

      When, in my main method i do the following:

      Throwers.fmap(length).f(readLn)))

      i get a compilation error, because f is expecting a [String, Throwable] (specifically), and readLn is of type [String, IOException]

      Now i understand that E extends Throwable should cover that ground, but it doesnt..

      I tried looking harder, and i realized, that when we call fmap, we give it the length function, which has A defined to be String, but i guess since it doesnt define E at all, the compiler assumes it is a plain Throwable..

      • Hi, Shlomi.

        This is a problem with variance. The “E extends Throwable” type parameter to fmap should take care of this. Try explicitly giving that argument:

        Throwers.<Int,String,IOException>fmap(length).f(readLn)

      • hey runar, thank you for your reply, that did the job..

        do you know why i had to do this, and the “E extends Throwable” didnt help?…

        10x again!

  6. You had to do this because Java only has very limited type inference. In Java, when in doubt, add more type annotation.

    • Yes, thank you. I already begin to see my bosses getting pissed at me writing things no one can read :)

      i must say that functional programming got me really intrigued, but i feel like iam missing alot of theoretical background. You seem to be really on top of this topic, are there any books you could recommended that could help me start swimming in this field?

      • Programming in Haskell by Graham Hutton is a good book on functional programming.

  7. Pingback: fmap « Marco Faustinelli's Blog

  8. Pingback: *pop* — Dave's Programming Blog

  9. Hi.

    By simply copy/paste Foo class code in an IDE, I saw that “;” was missing in the last line :

    {return s.length();}}}
    should be
    {return s.length();}};}

    By the way, I’ll have to finish the lazy error series, but I still get a glimpse of all your publications and it seems really very interesting. Thanks for the work and for sharing it.

  10. Hi,

    I am having the same problem as Shlomi, but the fix dopn’t work for me. In fact, in

    Throwers.fmap(length).f(readLn)

    , I do no see what Int is ?

  11. Really nice! Thanks for that post!

    How would you go about closing resources which you might normally do in a finally block? Would this have to happen within the body of the extract() method – catching, closing and rethrowing the exception?

Leave a comment