Skip to content

Instantly share code, notes, and snippets.

@SegFaultAX
Last active May 14, 2018 23:28
Show Gist options
  • Save SegFaultAX/e2173e8e0820adb8958e8c9ccd1a338f to your computer and use it in GitHub Desktop.
Save SegFaultAX/e2173e8e0820adb8958e8c9ccd1a338f to your computer and use it in GitHub Desktop.
Example type-safe pattern matching [Java]
package com.mkbernard.functional.examples;
import java.util.List;
import java.util.function.Function;
import com.google.common.collect.ImmutableList;
public abstract class Expr<A> {
public abstract <T> T match(Function<Value<A>, T> value, Function<Add<A>, T> add);
public static class Value<A> extends Expr<A> {
private final A value;
public Value(A value) {
this.value = value;
}
public static <A> Value<A> of(A v) {
return new Value<>(v);
}
@Override
public <T> T match(Function<Value<A>, T> value, Function<Add<A>, T> add) {
return value.apply(this);
}
public A getValue() {
return value;
}
}
public static class Add<A> extends Expr<A> {
private final Expr<A> a;
private final Expr<A> b;
public Add(Expr<A> a, Expr<A> b) {
this.a = a;
this.b = b;
}
public static <A> Add<A> of(Expr<A> a, Expr<A> b) {
return new Add<>(a, b);
}
@Override
public <T> T match(Function<Value<A>, T> value, Function<Add<A>, T> add) {
return add.apply(this);
}
public Expr<A> getA() {
return a;
}
public Expr<A> getB() {
return b;
}
}
public static int eval(Expr<Integer> e) {
return e.match(
(value) -> value.getValue(),
(add) -> eval(add.getA()) + eval(add.getB())
);
}
public static <T> List<T> evalOther(Expr<T> e) {
return e.match(
(value) -> ImmutableList.of(value.getValue()),
(add) -> ImmutableList.<T>builder().addAll(evalOther(add.getA())).addAll(evalOther(add.getB())).build()
);
}
public static void main(String[] args) {
Expr<Integer> e = Add.of(Value.of(1), Value.of(2));
System.out.println(eval(e));
System.out.println(evalOther(e));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment