let rec differentiate_aux = function
| Lambda(l) -> Lambda(0.)
| Id(x) -> Lambda(1.)
| Sin(f) -> Prod( (differentiate_aux f), Cos(f) )
| Cos(f) -> Prod( (differentiate_aux f), ( Prod(Lambda(-1.), (Sin(f)))) )
| Exp(f) -> Prod( (differentiate_aux f), Exp(f) )
| Ln(f) -> Prod( (differentiate_aux f), Inv(f) )
| Prod(f,g) -> Sum( (Prod((differentiate_aux f), g)), (Prod(f, (differentiate_aux g))) )
| Inv(f) -> Prod( ( Prod(Lambda(-1.), (differentiate_aux f)) ), (Power(f, -2)) )
| Sum(f,g) -> Sum((differentiate_aux f), (differentiate_aux g))
| Power(f,0) -> Lambda(0.)
| Power(f,1) -> differentiate_aux f
| Power(f,n) -> Prod( (Prod( (Lambda(float_of_int n)), (differentiate_aux f) )), (Power( f, n-1 )) )
| Comp(f,g) -> Prod( (differentiate_aux g), (Comp( (differentiate_aux f), g )) )
| Unknown(s) -> Unknown( (sprint "%s'" s) )