Skip to content

Instantly share code, notes, and snippets.

@hencjo
Created November 28, 2016 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hencjo/56131383d8a14fbe1ffad9d6e9fc8eed to your computer and use it in GitHub Desktop.
Save hencjo/56131383d8a14fbe1ffad9d6e9fc8eed to your computer and use it in GitHub Desktop.
import java.util.function.Function;
import static java.util.Objects.requireNonNull;
public class SumTypeDemo {
//Evaluate
private static int evaluate(Expression expression) {
return expression.expression.destruct(
constant -> constant.value,
add -> evaluate(add.a) + evaluate(add.b),
multiply -> evaluate(multiply.a) * evaluate(multiply.b)
);
}
//Usage
public static void main(String[] args) {
Expression expression = Expression.add(
Expression.multiply(Expression.constant(5), Expression.constant(10)),
Expression.constant(14)
);
int evaluate = evaluate(expression);
System.out.println(evaluate);
}
public static final class Constant {
public final int value;
public Constant(int value) {
this.value = value;
}
}
public static final class Add {
public final Expression a;
public final Expression b;
public Add(Expression a, Expression b) {
this.a = a;
this.b = b;
}
}
// Declaration of ADTs.
public static final class Multiply {
public final Expression a;
public final Expression b;
public Multiply(Expression a, Expression b) {
this.a = a;
this.b = b;
}
}
public static final class Expression {
public final U3<Constant, Add, Multiply> expression;
private Expression(U3<Constant, Add, Multiply> expression) {
this.expression = expression;
}
public static Expression constant(int value) {
return new Expression(U3.a(new Constant(value)));
}
public static Expression add(Expression a, Expression b) {
return new Expression(U3.b(new Add(a, b)));
}
public static Expression multiply(Expression a, Expression b) {
return new Expression(U3.c(new Multiply(a, b)));
}
}
// Library class - reused for all Sum Types.
public static final class U3<A, B, C> {
private final A a;
private final B b;
private final C c;
private U3(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}
public <A2,B2, C2> U3<A2,B2, C2> map(Function<A,A2> fa, Function<B,B2> fb, Function<C,C2> fc) {
if (a != null) return a(fa.apply(a));
if (b != null) return b(fb.apply(b));
return c(fc.apply(c));
}
public <X> X destruct(Function<A, X> fa, Function<B, X> fb, Function<C, X> fc) {
if (a != null) return fa.apply(a);
if (b != null) return fb.apply(b);
return fc.apply(c);
}
public static <A,B,C> U3<A,B,C> a(A a) {
return new U3<>(requireNonNull(a), null, null);
}
public static <A,B,C> U3<A,B,C> b(B b) {
return new U3<>(null, requireNonNull(b), null);
}
public static <A,B,C> U3<A,B,C> c(C c) {
return new U3<>(null, null, requireNonNull(c));
}
@Override
public String toString() {
if (a != null) return "(U3 " + a + ")";
if (b != null) return "(U3 " + b + ")";
return "(U3 " + c + ")";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
U3<?, ?, ?> u3 = (U3<?, ?, ?>) o;
if (a != null ? !a.equals(u3.a) : u3.a != null) return false;
if (b != null ? !b.equals(u3.b) : u3.b != null) return false;
return c != null ? c.equals(u3.c) : u3.c == null;
}
@Override
public int hashCode() {
int result = a != null ? a.hashCode() : 0;
result = 31 * result + (b != null ? b.hashCode() : 0);
result = 31 * result + (c != null ? c.hashCode() : 0);
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment