Skip to content

Instantly share code, notes, and snippets.

@dbaltor
Created February 3, 2019 17:50
Show Gist options
  • Save dbaltor/d5ed64562d59d85218d8b1164bdd4110 to your computer and use it in GitHub Desktop.
Save dbaltor/d5ed64562d59d85218d8b1164bdd4110 to your computer and use it in GitHub Desktop.
Implementing Monads in Java 8
import java.util.function.Function;
public class FunctorsMonads {
public static void main(String[] args) {
System.out.println(tryParse("47"));
System.out.println(tryParse("a"));
FOptional<String> str = FOptional.of("47");
System.out.println(str);
FOptional<FOptional<Integer>> num1 = str.map(FunctorsMonads::tryParse);
System.out.println(num1);
FOptional<Integer> num2 = str.flatMap(FunctorsMonads::tryParse);
System.out.println(num2);
}
static FOptional<Integer> tryParse(String s){
try {
final int i = Integer.parseInt(s);
return FOptional.of(i);
} catch (NumberFormatException e) {
return FOptional.empty();
}
}
}
interface Functor<T, F extends Functor<?, ?>> {
<R> F map(Function<T, R> f);
}
interface Monad<T, M extends Monad<?, ?>> extends Functor<T, M> {
M flatMap(Function<T, M> f); // From original article
//<R> M flatMap(Function<T, FOptional<R>> f); // Compiles but polutes the interface
//<R> M<R> flatMap(Function<T, M<R>> f);
/* You cannot implement a fully type-safe Monad interface in Java.
The correct signature for flatmap would be something like <R> M<R> flatMap(Function<T, M<R>> f),
but this is not expressible in Java. This M<R> expression is called a higher-kinded type
(http://dev.stephendiehl.com/fun/001_basics.html#higher-kinded-types).*/
}
//class FOptional<T> implements Functor<T, FOptional<?>>
class FOptional<T> implements Monad<T, FOptional<?>> {
private final T valueOrNull;
private FOptional(T valueOrNull) {
this.valueOrNull = valueOrNull;
}
public <R> FOptional<R> map(Function<T, R> f) {
if (valueOrNull == null)
return empty();
else
return of(f.apply(valueOrNull));
}
//public FOptional<?> flatMap(Function<T, FOptional<?>> f) { // wrong asnwer from Stackoverflow. It doesn't return FOptional<Integer>
public <R> FOptional<R> flatMap(Function<T, FOptional<R>> f) {
if (valueOrNull == null)
return empty();
else
return f.apply(valueOrNull);
}
public static <T> FOptional<T> of(T a) {
return new FOptional<T>(a);
}
public static <T> FOptional<T> empty() {
return new FOptional<T>(null);
}
@Override
public String toString() {
return getClass().getName() + "<" + valueOrNull + ">";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment