package com.acme.symbolic; import static church.lang.operators.Arithmetic.*; import static church.lang.operators.Relational.$$equal; import static com.acme.symbolic.Expression.Visitor; @SuppressWarnings("unchecked") public class Derivative { private static interface $I0<T> { public Expression<T> pd(Expression<T> exp); } public static interface $Derivative<T> { public Expression<T> derivative(church.lang.Functions.Function1<String, church.lang.Functions.Function1<Expression<T>, Expression<T>>> funNameToDerivative, Expression<T> exp0, Expression<T> x); } public static <T> $Derivative<T> derivative($Additive_identity<Expression<T>> $L0, $$equal<Expression<T>> $L1, $Multiplicative_identity<Expression<T>> $L2, $$prd<Expression<T>, Expression<T>> $L3, $$sum<Expression<T>> $L4, $$neg<Expression<T>> $L5, $$sub<Expression<T>> $L6, $$div<Expression<T>, Expression<T>> $L7, $$pow<Expression<T>, T> $L8, $$sub<T> $L9, $Multiplicative_identity<T> $L10) { return (funNameToDerivative, exp0, x) -> { $I0<T> pd = new $I0<T>() { public Expression<T> pd(Expression<T> exp) { return new Visitor<T, Expression<T>>() { public Expression<T> $const(T value) { return $L0.additive_identity(); } public Expression<T> var(String name) { return $L1.$equal(x, exp) ? $L2.multiplicative_identity() : $L0.additive_identity(); } public Expression<T> app(String funName, Expression<T> a) { return $L3.$prd(pd(a), funNameToDerivative.of(funName).of(a)); } public Expression<T> sum(Expression<T> f, Expression<T> g) { return $L4.$sum(pd(f), pd(g)); } public Expression<T> neg(Expression<T> f) { return $L5.$neg(pd(f)); } public Expression<T> sub(Expression<T> f, Expression<T> g) { return $L6.$sub(pd(f), pd(g)); } public Expression<T> prd(Expression<T> f, Expression<T> g) { return $L4.$sum($L3.$prd(pd(f), g), $L3.$prd(pd(g), f)); } public Expression<T> div(Expression<T> f, Expression<T> g) { return $L7.$div($L6.$sub($L3.$prd(pd(f), g), $L3.$prd(pd(g), f)), $L3.$prd(g, g)); } public Expression<T> pow(Expression<T> f, T n) { return $L3.$prd($L3.$prd(pd(f), Expression.$const(n)), $L8.$pow(f, $L9.$sub(n, $L10.multiplicative_identity()))); } } .get(exp); } }; return pd.pd(exp0); }; } }