Is there a built-in support for monad that deals with exception handling? Something similar to Scala's Try. I am asking because I don't like unchecked exceptions.
A monad is just a wrapper around a type or data structure. So by 'wrapping' a class type (e.g. Integer) inside the Java Optional type, we add some functionality around it, like of(x) , isPresent() , orElse(c) and get() . To be more precise, a Monad always contains a bind() function, That translates to flatMap in Java.
Java 8 introduced Optional class which is a monad. It provides operational equivalent to a monad. For example return is a operation which takes a value and return the monad.
Java's CompletableFuture is a Monad given its methods thenCompose and thenApply , which correspond to >>= (bind) and fmap in Haskell. It is a well known fact that any Monad gives rise to an Applicative.
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala. util. Either type. Instances of Try[T] , are either an instance of scala.
There are at least two generally available (e.g. on Maven Central) - Vavr and Cyclops both have Try implementations that take a slightly differing approach.
Vavr's Try follows Scala's Try very closely. It will catch all 'non-fatal' exceptions thrown during the execution of it's combinators.
Cyclops Try will only catch explicitly configured exceptions (of course you can, by default, also have it catch everything), and the default mode of operating is only to catch during the initial population method. The reasoning behind this is so that Try behaves in a somewhat similar way to Optional - Optional doesn't encapsulate unexpected Null values (i.e. bugs), just places where we reasonable expect to have no value.
Here is an example Try With Resources from Cyclops
Try t2 = Try.catchExceptions(FileNotFoundException.class,IOException.class)
.init(()->PowerTuples.tuple(new BufferedReader(new FileReader("file.txt")),new FileReader("hello")))
.tryWithResources(this::read2);
And another example 'lifting' an existing method (that might divide by zero) to support error handling.
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.*;
import static com.aol.cyclops.lambda.api.AsAnyM.anyM;
import lombok.val;
val divide = Monads.liftM2(this::divide);
AnyM<Integer> result = divide.apply(anyM(Try.of(2, ArithmeticException.class)), anyM(Try.of(0)));
assertThat(result.<Try<Integer,ArithmeticException>>unwrapMonad().isFailure(),equalTo(true));
private Integer divide(Integer a, Integer b){
return a/b;
}
The "better-java-monads" project on GitHub has a Try monad for Java 8 here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With