[Haskell-cafe] Symbolic differentation using GHC's simplification
rules
Henning Thielemann
lemming at henning-thielemann.de
Tue Mar 22 03:52:21 EST 2005
I tried to implement symbolic differentation using GHC's simplification
rules. I assume that someone has already thought about this, right? I have
also heard that the rules system is not strong enough for implementing a
full computer algebra system.
But here is a simple trial and some questions and problems which arise:
1. How to specify a type class context to which the rules have to be
restricted? (see the first comment)
2. How to handle lambdas?
3. The module can only be used for compiled programs, since in GHCi
optimisation is not available.
{-# OPTIONS -O -fglasgow-exts #-}
module SymbolicDifferentation where
{- These rules need Num context. -- How to write that?
"derive/const" forall y. derive (const y) = const 0 ;
"derive/id" derive id = const 1 ;
"derive/compos" forall f g. derive (f . g) = derive f . g .* derive
g ;
-}
{-# RULES
"derive/plus" forall f g. derive (f .+ g) = derive f .+ derive g ;
"derive/minus" forall f g. derive (f .- g) = derive f .- derive g ;
"derive/times" forall f g. derive (f .* g) = derive f .* g .+ f .* derive g ;
"derive/divide" forall f g. derive (f ./ g) = derive f .* g .- f .* derive g ./ ((^2).g) ;
"derive/power" forall n. derive ((^) n) = (n*) . (^(n-1)) ;
"derive/sin" derive sin = cos ;
"derive/cos" derive cos = negate . sin ;
"derive/exp" derive exp = exp ;
"derive/log" derive log = recip ;
#-}
-- lift a binary operation to the function values
fop2 :: (c -> d -> e) -> (a -> c) -> (a -> d) -> (a -> e)
fop2 op f g x = op (f x) (g x)
infixl 6 .+, .-
infixl 7 .*, ./
(.+), (.-), (.*) :: Num a => (t -> a) -> (t -> a) -> (t -> a)
(./) :: Fractional a => (t -> a) -> (t -> a) -> (t -> a)
(.+) = fop2 (+)
(.-) = fop2 (-)
(.*) = fop2 (*)
(./) = fop2 (/)
derive :: (t -> a) -> (t -> a)
derive = error "Could not derive expression symbolically."
test :: IO ()
test =
do print (derive log 2)
print (derive sin 0)
print (derive cos 0.1)
print (derive (cos .+ sin) (pi/4))
print (derive (\x -> exp x) 0)
print (derive (\x -> x^2 + x) 0)
print (derive (exp . sin) 0)
More information about the Haskell-Cafe
mailing list