# dy/dx

Submitted by Greg Buchholz on Thu, 10/20/2005 - 2:23pm.

Over on comp.lang.lisp we have someone trying to use Haskell for a little symbolic differentiation problem. Since it doesn't even compile, I thought I'd throw my hat in the ring and clean it up a little (Is there a better way to display snippets on this site? I had to use <pre> tags instead of <code> tags)...

infixl 5 :+ infixl 6 :* data Exp = Num Integer | Var Sym | Exp :+ Exp | Exp :* Exp deriving (Eq,Show) data Sym = X | Y deriving (Eq,Show) main = do let exp = (Num 4 :* Var X :* Var X) let deriv = d exp X putStrLn $ "Original expression : " ++ (show exp) putStrLn $ "Derivative : " ++ (show $ simplify deriv) putStrLn $ "Derivative evaluated at X=10 : " ++ (show $ eval (d exp X) [(X,10)]) --take the derivative... d (Num n) x = Num 0 d (Var y) x | x==y = Num 1 | otherwise = Num 0 d (f :+ g) x = (d f x) :+ (d g x) d (f :* g) x = (d f x) :* g :+ f :* (d g x) --evaluate an Exp... eval (Num x) env = x eval (Var x) env = case (lookup x env) of (Just n) -> n (Nothing) -> error $ "no variable "++(show x)++" in env" eval (x :+ y) env = eval x env + eval y env eval (x :* y) env = eval x env * eval y env --a few algebraic simplification rules simp (x :+ y) | x == y = simp (Num 2):*x simp ((Num 0) :+ x) = simp x simp (x :+ (Num 0)) = simp x simp ((Num x) :+ (Num y)) = Num (x+y) simp (x :+ y) = simp x :+ simp y simp ((Num 0) :* x) = Num 0 simp (x :* (Num 0)) = Num 0 simp ((Num 1) :* x) = simp x simp (x :* (Num 1)) = simp x simp ((Num x) :* (Num y)) = Num (x*y) simp (x :* y) = simp x :* simp y simp x = x --apply simplification rules until the expression doesn't change anymore simplify x = let a = iterate simp x fix = dropWhile (\(c,d)->c/=d) $ zip a (tail a) in (fst.head) fix

- Greg Buchholz's blog
- Login to post comments