module Data.Derivative
(
(:>), powVal, derivative, derivativeAt
, (:~>), dZero, pureD
, fmapD, (<$>>), liftD2, liftD3
, idD, fstD, sndD
, linearD, distrib
, (@.), (>-<)
) where
import Data.Function (on)
import Data.VectorSpace
import Data.NumInstances ()
import Data.LinearMap
import qualified Data.Maclaurin as D
infixr 9 @.
infixl 4 <$>>
infix 0 >-<
newtype (a :> b) = T { unT :: a D.:> b }
deriving instance (VectorSpace b b, LMapDom a b, Num b ) => Num (a :> b)
deriving instance (VectorSpace b b, LMapDom a b, Fractional b) => Fractional (a :> b)
deriving instance (VectorSpace b b, LMapDom a b, Floating b ) => Floating (a :> b)
deriving instance (VectorSpace b s, LMapDom a s ) => AdditiveGroup (a :> b)
inT :: ((a D.:> b) -> (c D.:> d))
-> ((a :> b) -> (c :> d))
inT = (T .).(. unT)
inT2 :: ((a D.:> b) -> (c D.:> d) -> (e D.:> f))
-> ((a :> b) -> (c :> d) -> (e :> f))
inT2 = (inT .).(. unT)
inT3 :: ((a D.:> b) -> (c D.:> d) -> (e D.:> f) -> (g D.:> h))
-> ((a :> b) -> (c :> d) -> (e :> f) -> (g :> h))
inT3 = (inT2 .).(. unT)
powVal :: (a :> b) -> b
powVal = D.powVal . unT
derivative :: (VectorSpace b s, LMapDom a s) =>
(a :> b) -> (a :-* (a :> b))
derivative = fmapL T . D.derivative . unT
derivativeAt :: (LMapDom a s, VectorSpace b s) =>
(a :> b) -> a -> (a :> b)
derivativeAt d = T . D.derivativeAt (unT d)
type a :~> b = a -> (a:>b)
dZero :: (LMapDom a s, VectorSpace b s) => a:>b
dZero = T D.dZero
pureD :: (LMapDom a s, VectorSpace b s) => b -> a:>b
pureD = fmap T D.pureD
fmapD, (<$>>) :: (LMapDom a s, VectorSpace b s) =>
(b -> c) -> (a :> b) -> (a :> c)
fmapD = fmap inT D.fmapD
(<$>>) = fmapD
liftD2 :: (VectorSpace b s, LMapDom a s, VectorSpace c s, VectorSpace d s) =>
(b -> c -> d) -> (a :> b) -> (a :> c) -> (a :> d)
liftD2 = fmap inT2 D.liftD2
liftD3 :: ( LMapDom a s
, VectorSpace b s, VectorSpace c s
, VectorSpace d s, VectorSpace e s ) =>
(b -> c -> d -> e)
-> (a :> b) -> (a :> c) -> (a :> d) -> (a :> e)
liftD3 = fmap inT3 D.liftD3
idD :: (LMapDom u s, VectorSpace u s) => u :~> u
idD = fmap T D.idD
linearD :: (LMapDom u s, VectorSpace v s) => (u -> v) -> (u :~> v)
linearD = (fmap.fmap) T D.linearD
fstD :: (VectorSpace a s, LMapDom b s, LMapDom a s) => (a,b) :~> a
fstD = fmap T D.fstD
sndD :: (VectorSpace b s, LMapDom b s, LMapDom a s) => (a,b) :~> b
sndD = fmap T D.sndD
distrib :: (LMapDom a s, VectorSpace b s, VectorSpace c s, VectorSpace u s) =>
(b -> c -> u) -> (a :> b) -> (a :> c) -> (a :> u)
distrib = fmap inT2 D.distrib
instance Show b => Show (a :> b) where show = show . unT
instance Eq b => Eq (a :> b) where (==) = (==) `on` unT
instance Ord b => Ord (a :> b) where compare = compare `on` unT
instance (LMapDom a s, VectorSpace u s, VectorSpace s s)
=> VectorSpace (a :> u) (a :> s) where
(*^) = inT2 (D.**^)
instance (InnerSpace u s, InnerSpace s s', VectorSpace s s, LMapDom a s) =>
InnerSpace (a :> u) (a :> s) where
(<.>) = inT2 (D.<*.>)
(@.) :: (LMapDom b s, LMapDom a s, VectorSpace c s) =>
(b :~> c) -> (a :~> b) -> (a :~> c)
h @. g = T . ((unT . h) D.@. (unT . g))
(>-<) :: (LMapDom a s, VectorSpace s s, VectorSpace u s) =>
(u -> u) -> ((a :> u) -> (a :> s))
-> (a :> u) -> (a :> u)
f >-< f' = inT (f D.>-< (unT . f' . T))