Skip to content

Instantly share code, notes, and snippets.

@jbgi
Created October 8, 2018 18:05
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 jbgi/31b891f00566feb301f8100762ee8511 to your computer and use it in GitHub Desktop.
Save jbgi/31b891f00566feb301f8100762ee8511 to your computer and use it in GitHub Desktop.
Derive4J for extensible algebraic data types.
@Data
interface Exp {
interface ExpAlg<E, R> {
R Lit(int lit);
R Add(E e1, E e2);
}
<R> R accept(ExpAlg<Exp, R> alg);
}
@Data
interface ExpMul {
interface ExpMulAlg<E, R> extends Exp.ExpAlg<E, R> {
R Mul(E e1, E e2);
}
<R> R accept(ExpMulAlg<ExpMul, R> alg);
static Function<Exp, ExpMul> fromExp() {
ExpMulAlg<ExpMul, ExpMul> factory = ExpMuls.factory();
return Exps.cata(factory, ExpMuls::lazy);
}
}
//Generated by Derive4J:
import java.lang.Integer;
import java.lang.Override;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
final class ExpMuls {
private static final ExpMul.ExpMulAlg<ExpMul, Optional<Integer>> litGetter = ExpMuls.alg((lit) -> Optional.of(lit),
(e1, e2) -> Optional.empty(),
(e1, e2) -> Optional.empty());
private static final ExpMul.ExpMulAlg<ExpMul, Optional<ExpMul>> e1Getter = ExpMuls.alg((lit) -> Optional.empty(),
(e1, e2) -> Optional.of(e1),
(e1, e2) -> Optional.of(e1));
private static final ExpMul.ExpMulAlg<ExpMul, Optional<ExpMul>> e2Getter = ExpMuls.alg((lit) -> Optional.empty(),
(e1, e2) -> Optional.of(e2),
(e1, e2) -> Optional.of(e2));
private static final ExpMul.ExpMulAlg<ExpMul, ExpMul> factory = new LambdaExpMulAlg<>(ExpMuls::Lit, ExpMuls::Add, ExpMuls::Mul);
private ExpMuls() {
}
public static <R> ExpMul.ExpMulAlg<ExpMul, R> alg(Function<Integer, R> Lit,
AddMapper<ExpMul, R> Add, MulMapper<ExpMul, R> Mul) {
return new LambdaExpMulAlg<>(Lit, Add, Mul);
}
public static ExpMul Lit(int lit) {
return new Lit(lit);
}
public static ExpMul Add(ExpMul e1, ExpMul e2) {
return new Add(e1, e2);
}
public static ExpMul Mul(ExpMul e1, ExpMul e2) {
return new Mul(e1, e2);
}
public static ExpMul lazy(Supplier<ExpMul> expMul) {
return new Lazy(expMul);
}
public static CasesMatchers.TotalMatcher_Lit cases() {
return CasesMatchers.totalMatcher_Lit;
}
public static CaseOfMatchers.TotalMatcher_Lit caseOf(ExpMul expMul) {
return new CaseOfMatchers.TotalMatcher_Lit(expMul);
}
public static Optional<Integer> getLit(ExpMul expMul) {
return expMul.accept(litGetter);
}
public static Optional<ExpMul> getE1(ExpMul expMul) {
return expMul.accept(e1Getter);
}
public static Optional<ExpMul> getE2(ExpMul expMul) {
return expMul.accept(e2Getter);
}
public static Function<ExpMul, ExpMul> setLit(Integer newLit) {
return modLit(__ -> newLit);
}
public static Function<ExpMul, ExpMul> modLit(Function<Integer, Integer> litMod) {
ExpMul.ExpMulAlg<ExpMul, ExpMul> expMulAlg = org.derive4j.example.algebras.ExpMuls.alg((lit) -> Lit(litMod.apply(lit)),
ExpMuls::Add,
ExpMuls::Mul);
return expMul -> expMul.accept(expMulAlg);
}
public static Function<ExpMul, ExpMul> setE1(ExpMul newE1) {
return modE1(__ -> newE1);
}
public static Function<ExpMul, ExpMul> modE1(Function<ExpMul, ExpMul> e1Mod) {
ExpMul.ExpMulAlg<ExpMul, ExpMul> expMulAlg = org.derive4j.example.algebras.ExpMuls.alg(ExpMuls::Lit,
(e1, e2) -> Add(e1Mod.apply(e1), e2),
(e1, e2) -> Mul(e1Mod.apply(e1), e2));
return expMul -> expMul.accept(expMulAlg);
}
public static Function<ExpMul, ExpMul> setE2(ExpMul newE2) {
return modE2(__ -> newE2);
}
public static Function<ExpMul, ExpMul> modE2(Function<ExpMul, ExpMul> e2Mod) {
ExpMul.ExpMulAlg<ExpMul, ExpMul> expMulAlg = org.derive4j.example.algebras.ExpMuls.alg(ExpMuls::Lit,
(e1, e2) -> Add(e1, e2Mod.apply(e2)),
(e1, e2) -> Mul(e1, e2Mod.apply(e2)));
return expMul -> expMul.accept(expMulAlg);
}
public static <R> Function<ExpMul, R> cata(Function<Integer, R> Lit, AddMapper<R, R> Add,
MulMapper<R, R> Mul, Function<Supplier<R>, R> delay) {
return cata(new LambdaExpMulAlg<>(Lit, Add, Mul), delay);
}
public static <R> Function<ExpMul, R> cata(ExpMul.ExpMulAlg<R, R> expMulAlg,
Function<Supplier<R>, R> delay) {
ExpMul.ExpMulAlg<ExpMul, R> lazyExpMulAlg = new CataExpMulAlg<>(expMulAlg, delay);
return expMul -> delay.apply(() -> expMul.accept(lazyExpMulAlg));
}
public static ExpMul.ExpMulAlg<ExpMul, ExpMul> factory() {
return factory;
}
public interface AddMapper<E, R> {
R Add(E e1, E e2);
}
public interface MulMapper<E, R> {
R Mul(E e1, E e2);
}
private static final class LambdaExpMulAlg<E, R> implements ExpMul.ExpMulAlg<E, R> {
private final Function<Integer, R> Lit;
private final AddMapper<E, R> Add;
private final MulMapper<E, R> Mul;
LambdaExpMulAlg(Function<Integer, R> Lit, AddMapper<E, R> Add, MulMapper<E, R> Mul) {
this.Lit = Lit;
this.Add = Add;
this.Mul = Mul;
}
@Override
public R Lit(int lit) {
return this.Lit.apply(lit);
}
@Override
public R Add(E e1, E e2) {
return this.Add.Add(e1, e2);
}
@Override
public R Mul(E e1, E e2) {
return this.Mul.Mul(e1, e2);
}
}
private static final class Lit implements ExpMul {
private final int lit;
Lit(int lit) {
this.lit = lit;
}
@Override
public <R> R accept(ExpMul.ExpMulAlg<ExpMul, R> alg) {
return alg.Lit(this.lit);
}
}
private static final class Add implements ExpMul {
private final ExpMul e1;
private final ExpMul e2;
Add(ExpMul e1, ExpMul e2) {
this.e1 = e1;
this.e2 = e2;
}
@Override
public <R> R accept(ExpMul.ExpMulAlg<ExpMul, R> alg) {
return alg.Add(this.e1, this.e2);
}
}
private static final class Mul implements ExpMul {
private final ExpMul e1;
private final ExpMul e2;
Mul(ExpMul e1, ExpMul e2) {
this.e1 = e1;
this.e2 = e2;
}
@Override
public <R> R accept(ExpMul.ExpMulAlg<ExpMul, R> alg) {
return alg.Mul(this.e1, this.e2);
}
}
private static final class Lazy implements ExpMul {
private volatile Supplier<ExpMul> expression;
private ExpMul evaluation;
Lazy(Supplier<ExpMul> expMul) {
this.expression = expMul;
}
private synchronized ExpMul _evaluate() {
Lazy lazy = this;
while (true) {
Supplier<ExpMul> expr = lazy.expression;
if (expr == null) {
evaluation = lazy.evaluation;
break;
}
else {
ExpMul eval = expr.get();
if (eval instanceof Lazy) {
lazy = (Lazy) eval;
}
else {
evaluation = eval;
break;
}
}
}
expression = null;
return evaluation;
}
@Override
public <R> R accept(ExpMul.ExpMulAlg<ExpMul, R> alg) {
return (this.expression == null ? this.evaluation : _evaluate()).accept(alg);
}
}
public static class CasesMatchers {
private static final TotalMatcher_Lit totalMatcher_Lit = new TotalMatcher_Lit();
private CasesMatchers() {
}
public static final class TotalMatcher_Lit {
TotalMatcher_Lit() {
}
public final <R> TotalMatcher_Add<R> Lit(Function<Integer, R> Lit) {
return new TotalMatcher_Add<>(Lit);
}
public final <R> TotalMatcher_Add<R> Lit_(R r) {
return this.Lit((lit) -> r);
}
public final <R> PartialMatcher_Mul<R> Add(AddMapper<ExpMul, R> Add) {
return new PartialMatcher_Mul<>(null, Add);
}
public final <R> PartialMatcher_Mul<R> Add_(R r) {
return this.Add((e1, e2) -> r);
}
public final <R> PartialMatcher<R> Mul(MulMapper<ExpMul, R> Mul) {
return new PartialMatcher<>(null, null, Mul);
}
public final <R> PartialMatcher<R> Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static final class TotalMatcher_Add<R> extends PartialMatcher_Mul<R> {
TotalMatcher_Add(Function<Integer, R> Lit) {
super(Lit, null);
}
public final TotalMatcher_Mul<R> Add(AddMapper<ExpMul, R> Add) {
return new TotalMatcher_Mul<>(((PartialMatcher<R>) this).Lit, Add);
}
public final TotalMatcher_Mul<R> Add_(R r) {
return this.Add((e1, e2) -> r);
}
}
public static final class TotalMatcher_Mul<R> extends PartialMatcher<R> {
TotalMatcher_Mul(Function<Integer, R> Lit, AddMapper<ExpMul, R> Add) {
super(Lit, Add, null);
}
public final Function<ExpMul, R> Mul(MulMapper<ExpMul, R> Mul) {
ExpMul.ExpMulAlg<ExpMul, R> alg = ExpMuls.alg(((PartialMatcher<R>) this).Lit, ((PartialMatcher<R>) this).Add, Mul);
return expMul -> expMul.accept(alg);
}
public final Function<ExpMul, R> Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static class PartialMatcher_Mul<R> extends PartialMatcher<R> {
PartialMatcher_Mul(Function<Integer, R> Lit, AddMapper<ExpMul, R> Add) {
super(Lit, Add, null);
}
public final PartialMatcher<R> Mul(MulMapper<ExpMul, R> Mul) {
return new PartialMatcher<>(((PartialMatcher<R>) this).Lit, ((PartialMatcher<R>) this).Add, Mul);
}
public final PartialMatcher<R> Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static class PartialMatcher<R> {
private final Function<Integer, R> Lit;
private final AddMapper<ExpMul, R> Add;
private final MulMapper<ExpMul, R> Mul;
PartialMatcher(Function<Integer, R> Lit, AddMapper<ExpMul, R> Add, MulMapper<ExpMul, R> Mul) {
this.Lit = Lit;
this.Add = Add;
this.Mul = Mul;
}
public final Function<ExpMul, R> otherwise(Supplier<R> otherwise) {
ExpMul.ExpMulAlg<ExpMul, R> alg = ExpMuls.<R>alg(this.Lit != null ? this.Lit : (lit) -> otherwise.get(),
this.Add != null ? this.Add : (e1, e2) -> otherwise.get(),
this.Mul != null ? this.Mul : (e1, e2) -> otherwise.get());
return expMul -> expMul.accept(alg);
}
public final Function<ExpMul, R> otherwise_(R r) {
return this.otherwise(() -> r);
}
public final Function<ExpMul, Optional<R>> otherwiseEmpty() {
ExpMul.ExpMulAlg<ExpMul, Optional<R>> alg = ExpMuls.alg((this.Lit != null) ? (lit) -> Optional.of(this.Lit.apply(lit))
: (lit) -> Optional.empty(),
(this.Add != null) ? (e1, e2) -> Optional.of(this.Add.Add(e1, e2))
: (e1, e2) -> Optional.empty(),
(this.Mul != null) ? (e1, e2) -> Optional.of(this.Mul.Mul(e1, e2))
: (e1, e2) -> Optional.empty());
return expMul -> expMul.accept(alg);
}
}
}
public static class CaseOfMatchers {
private CaseOfMatchers() {
}
public static final class TotalMatcher_Lit {
private final ExpMul _expMul;
TotalMatcher_Lit(ExpMul _expMul) {
this._expMul = _expMul;
}
public final <R> TotalMatcher_Add<R> Lit(Function<Integer, R> Lit) {
return new TotalMatcher_Add<>(this._expMul, Lit);
}
public final <R> TotalMatcher_Add<R> Lit_(R r) {
return this.Lit((lit) -> r);
}
public final <R> PartialMatcher_Mul<R> Add(AddMapper<ExpMul, R> Add) {
return new PartialMatcher_Mul<>(this._expMul, null, Add);
}
public final <R> PartialMatcher_Mul<R> Add_(R r) {
return this.Add((e1, e2) -> r);
}
public final <R> PartialMatcher<R> Mul(MulMapper<ExpMul, R> Mul) {
return new PartialMatcher<>(this._expMul, null, null, Mul);
}
public final <R> PartialMatcher<R> Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static final class TotalMatcher_Add<R> extends PartialMatcher_Mul<R> {
TotalMatcher_Add(ExpMul _expMul, Function<Integer, R> Lit) {
super(_expMul, Lit, null);
}
public final TotalMatcher_Mul<R> Add(AddMapper<ExpMul, R> Add) {
return new TotalMatcher_Mul<>(((PartialMatcher<R>) this)._expMul, ((PartialMatcher<R>) this).Lit, Add);
}
public final TotalMatcher_Mul<R> Add_(R r) {
return this.Add((e1, e2) -> r);
}
}
public static final class TotalMatcher_Mul<R> extends PartialMatcher<R> {
TotalMatcher_Mul(ExpMul _expMul, Function<Integer, R> Lit, AddMapper<ExpMul, R> Add) {
super(_expMul, Lit, Add, null);
}
public final R Mul(MulMapper<ExpMul, R> Mul) {
ExpMul.ExpMulAlg<ExpMul, R> alg = ExpMuls.alg(((PartialMatcher<R>) this).Lit, ((PartialMatcher<R>) this).Add, Mul);
return ((PartialMatcher<R>) this)._expMul.accept(alg);
}
public final R Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static class PartialMatcher_Mul<R> extends PartialMatcher<R> {
PartialMatcher_Mul(ExpMul _expMul, Function<Integer, R> Lit, AddMapper<ExpMul, R> Add) {
super(_expMul, Lit, Add, null);
}
public final PartialMatcher<R> Mul(MulMapper<ExpMul, R> Mul) {
return new PartialMatcher<>(((PartialMatcher<R>) this)._expMul, ((PartialMatcher<R>) this).Lit, ((PartialMatcher<R>) this).Add, Mul);
}
public final PartialMatcher<R> Mul_(R r) {
return this.Mul((e1, e2) -> r);
}
}
public static class PartialMatcher<R> {
private final ExpMul _expMul;
private final Function<Integer, R> Lit;
private final AddMapper<ExpMul, R> Add;
private final MulMapper<ExpMul, R> Mul;
PartialMatcher(ExpMul _expMul, Function<Integer, R> Lit, AddMapper<ExpMul, R> Add,
MulMapper<ExpMul, R> Mul) {
this._expMul = _expMul;
this.Lit = Lit;
this.Add = Add;
this.Mul = Mul;
}
public final R otherwise(Supplier<R> otherwise) {
ExpMul.ExpMulAlg<ExpMul, R> alg = ExpMuls.<R>alg(this.Lit != null ? this.Lit : (lit) -> otherwise.get(),
this.Add != null ? this.Add : (e1, e2) -> otherwise.get(),
this.Mul != null ? this.Mul : (e1, e2) -> otherwise.get());
return this._expMul.accept(alg);
}
public final R otherwise_(R r) {
return this.otherwise(() -> r);
}
public final Optional<R> otherwiseEmpty() {
ExpMul.ExpMulAlg<ExpMul, Optional<R>> alg = ExpMuls.alg((this.Lit != null) ? (lit) -> Optional.of(this.Lit.apply(lit))
: (lit) -> Optional.empty(),
(this.Add != null) ? (e1, e2) -> Optional.of(this.Add.Add(e1, e2))
: (e1, e2) -> Optional.empty(),
(this.Mul != null) ? (e1, e2) -> Optional.of(this.Mul.Mul(e1, e2))
: (e1, e2) -> Optional.empty());
return this._expMul.accept(alg);
}
}
}
private static final class CataExpMulAlg<R> implements ExpMul.ExpMulAlg<ExpMul, R> {
private final ExpMul.ExpMulAlg<R, R> expMulAlg;
private final Function<Supplier<R>, R> delay;
CataExpMulAlg(ExpMul.ExpMulAlg<R, R> expMulAlg, Function<Supplier<R>, R> delay) {
this.expMulAlg = expMulAlg;
this.delay = delay;
}
@Override
public R Lit(int lit) {
return this.expMulAlg.Lit(lit);
}
@Override
public R Add(ExpMul e1, ExpMul e2) {
return this.expMulAlg.Add(this.delay.apply(() -> e1.accept(this)), this.delay.apply(() -> e2.accept(this)));
}
@Override
public R Mul(ExpMul e1, ExpMul e2) {
return this.expMulAlg.Mul(this.delay.apply(() -> e1.accept(this)), this.delay.apply(() -> e2.accept(this)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment