module Data.Ring.Module.AutomaticDifferentiation
( module Data.Ring.Module
, D
) where
import Prelude hiding ((*),(+),(),subtract,negate)
import Data.Ring.Sugar
import Data.Ring.Module
import Data.Monoid.Reducer
import Test.QuickCheck
import Control.Monad
data D r m = D r m
instance (Monoid r, Monoid m) => Monoid (D r m) where
mempty = D mempty mempty
D x m `mappend` D y n = D (x + y) (m + n)
instance (Module r m) => Multiplicative (D r m) where
one = D one zero
D x m `times` D y n = D (x * y) (x *. n + m .* y)
instance (Group r, Module r m, Group m) => Group (D r m) where
gnegate (D x m) = D (gnegate x) (gnegate m)
D x m `minus` D y n = D (x `minus` y) (m `minus` n)
D x m `gsubtract` D y n = D (x `gsubtract` y) (m `gsubtract` n)
instance (LeftSemiNearRing r, Module r m) => LeftSemiNearRing (D r m)
instance (RightSemiNearRing r, Module r m) => RightSemiNearRing (D r m)
instance (SemiRing r, Module r m) => SemiRing (D r m)
instance (Ring r, Module r m, Group m) => Ring (D r m)
instance (c `Reducer` r, c `Reducer` m) => Reducer c (D r m) where
unit c = D (unit c) (unit c)
c `cons` D x m = D (c `cons` x) (c `cons` m)
D x m `snoc` c = D (x `snoc` c) (m `snoc` c)
instance (Arbitrary r, Arbitrary m) => Arbitrary (D r m) where
arbitrary = liftM2 D arbitrary arbitrary
shrink (D r m) = liftM2 D (shrink r) (shrink m)
instance (CoArbitrary r, CoArbitrary m) => CoArbitrary (D r m) where
coarbitrary (D r m) = coarbitrary r >< coarbitrary m