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 _______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
