[Haskell-cafe] Safe forward-mode AD in Haskell?
David Roundy
droundy at darcs.net
Tue May 8 21:44:00 EDT 2007
Okay, here's an alternate, unbranded approach:
> data Bundle a = Bundle a a
> instance Num a => Show (Bundle a) where
> showsPrec p (Bundle x x') = showsPrec p [x,x']
> instance Num a => Eq (Bundle a) where
> (Bundle x x') == (Bundle y y') = (x == y)
> instance Num a => Num (Bundle a) where
> (Bundle x x') + (Bundle y y') = Bundle (x + y) (x' + y')
> (Bundle x x') * (Bundle y y') = Bundle (x * y) (x * y' + x' * y)
> fromInteger z = Bundle (fromInteger z) 0
> lift z = Bundle z 0
> d :: Num a => (forall b. (Num b) => (a -> b) -> b -> b) -> a -> a
> d f x = let (Bundle y y') = f lift (Bundle x 1) in y'
The key change is in the type of d, which now accepts a polymorphic
function on numbers, but passes in a "lift" function, which allows us to
pass in higher-level variables. In one sense this function is ugly. In
another sense, it's prettier, as you can now hide *all* of the Bundle data
in a "differentiation" module.
> constant_one x = d (\l y -> l x + y) 1
> should_be_one_a = d (\_ x -> x * (constant_one x)) 1
> should_be_one_b = d (\_ x -> x * 1 ) 1
> violation_of_referential_transparency =
> should_be_one_a /= should_be_one_b
--
David Roundy
Department of Physics
Oregon State University
More information about the Haskell-Cafe
mailing list