Skip to content

Instantly share code, notes, and snippets.

@ahamid
Created June 10, 2011 22:13
Show Gist options
  • Save ahamid/1019897 to your computer and use it in GitHub Desktop.
Save ahamid/1019897 to your computer and use it in GitHub Desktop.
Monad in Java
// Created on Feb 7, 2009
package snippet;
import java.math.BigDecimal;
public class Monad {
// this is our "side effect" ("amplified object")
public static class AnnotatedObject<T> {
public T o;
public String note;
}
public static <T> AnnotatedObject<T> performAnnotationSideEffect(T t, String note) {
AnnotatedObject<T> ao = new AnnotatedObject<T>();
ao.o = t;
ao.note = note;
return ao;
}
public static interface IntegerToAnnotatedStringFunction {
public AnnotatedObject<String> invoke(Integer i);
}
public static class DefaultIntegerToAnnotatedStringFunction implements IntegerToAnnotatedStringFunction {
public AnnotatedObject<String> invoke(Integer i) {
AnnotatedObject<String> ao = performAnnotationSideEffect(i.toString(), "Converted integer " + i + " to string");
return ao;
}
}
public static interface StringToAnnotatedBigDecimalFunction {
public AnnotatedObject<BigDecimal> invoke(String s);
}
public static class DefaultStringToAnnotatedBigDecimalFunction implements StringToAnnotatedBigDecimalFunction {
public AnnotatedObject<BigDecimal> invoke(String s) {
AnnotatedObject<BigDecimal> ao = performAnnotationSideEffect(new BigDecimal(s), "Converted string " + s + " to bigdecimal");
return ao;
}
}
// now I want to compose the two functions to get Integer -> AnnotatedObject<BigDecimal>
public static interface IntegerToAnnotatedBigDecimalFunction {
public AnnotatedObject<BigDecimal> invoke(Integer i);
}
public static class Compose {
public IntegerToAnnotatedBigDecimalFunction invoke(final StringToAnnotatedBigDecimalFunction f, final IntegerToAnnotatedStringFunction g) {
return new IntegerToAnnotatedBigDecimalFunction() {
public AnnotatedObject<BigDecimal> invoke(Integer i) {
//return f.invoke(g.invoke(i)); // XXX type error, canna doit captin!
return null;
}
};
}
}
// we need a function that takes an AnnotatedObject<String> and can produce a function String->AnnotatedObject<BigDecimal>
public static interface AnnotationMonad {
public IntegerToAnnotatedBigDecimalFunction BIND(AnnotatedObject<String> s, StringToAnnotatedBigDecimalFunction f);
}
public static class DefaultAnnotationMonad {
public IntegerToAnnotatedBigDecimalFunction BIND(final AnnotatedObject<String> s, final StringToAnnotatedBigDecimalFunction f) {
// in here we deal with combining "side-effects"!
// they are the same "type" of side effect, so we should be able to come up with a way to combine them (?)
return new IntegerToAnnotatedBigDecimalFunction() {
public AnnotatedObject<BigDecimal> invoke(Integer i) {
AnnotatedObject<BigDecimal> result = f.invoke(s.o);
result.note = s.note + result.note; // append to the previous note
return result;
}
};
}
}
public static class ComposeWithMonads {
public IntegerToAnnotatedBigDecimalFunction invoke(final StringToAnnotatedBigDecimalFunction f, final IntegerToAnnotatedStringFunction g) {
return new IntegerToAnnotatedBigDecimalFunction() {
public AnnotatedObject<BigDecimal> invoke(Integer i) {
return new DefaultAnnotationMonad().BIND(g.invoke(i), f).invoke(i);
}
};
}
}
public static void main(String[] args) {
Integer i = new Integer(100);
AnnotatedObject<BigDecimal> o = new ComposeWithMonads().invoke(new DefaultStringToAnnotatedBigDecimalFunction(), new DefaultIntegerToAnnotatedStringFunction()).invoke(i);
System.out.println(o.o);
System.out.println(o.note);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment