datatype exp =
| EXPcst of double
| EXPvar of string
| EXPadd of (exp, exp)
| EXPsub of (exp, exp)
| EXPmul of (exp, exp)
| EXPdiv of (exp, exp)
| EXPpow of (exp, int)
val expcst_0 = EXPcst 0.0 and expcst_1 = EXPcst 1.0
fn exp_derivate
(e0: exp, x0: string): exp = let
fun aux (e0: exp):<cloref1> exp =
case+ e0 of
| EXPcst _ => expcst_0
| EXPvar x => begin
if eq_string_string (x, x0) then expcst_1 else expcst_0
end | EXPadd (e1, e2) => EXPadd (aux e1, aux e2)
| EXPsub (e1, e2) => EXPsub (aux e1, aux e2)
| EXPmul (e1, e2) => begin
EXPadd (EXPmul (aux e1, e2), EXPmul (e1, aux e2))
end
| EXPdiv (e1, e2) => EXPdiv (
EXPsub (EXPmul (aux e1, e2), EXPmul (e1, aux e2)), EXPpow (e2, 2)
) | EXPpow (e, n) => begin case+ n of
| _ when n = 1 => aux (e)
| _ when n = 0 => expcst_0
| _ => EXPmul (
EXPcst (double_of_int n), EXPmul (EXPpow (e, n-1), aux e)
)
end in
aux (e0)
end