packages feed

inf-backprop 0.1.1.0 → 0.2.0.0

raw patch · 28 files changed

+7413/−2381 lines, 28 filesdep +Streamdep +combinatorialdep +compositiondep −monad-loggerdep ~comonaddep ~isomorphism-classdep ~numhaskbinary-addedPVP ok

version bump matches the API change (PVP)

Dependencies added: Stream, combinatorial, composition, data-fix, deepseq, extra, finite-typelits, fixed-vector, ghc-prim, hashable, indexed-list-literals, lens, optics, primitive, profunctors, safe, unordered-containers, vector, vector-sized

Dependencies removed: monad-logger

Dependency ranges changed: comonad, isomorphism-class, numhask, simple-expr, text, transformers

API changes (from Hackage documentation)

- Control.CatBifunctor: (***) :: CatBiFunctor p cat => cat a1 b1 -> cat a2 b2 -> cat (p a1 a2) (p b1 b2)
- Control.CatBifunctor: class Category cat => CatBiFunctor (p :: Type -> Type -> Type) (cat :: Type -> Type -> Type)
- Control.CatBifunctor: first :: CatBiFunctor p cat => cat a b -> cat (p a c) (p b c)
- Control.CatBifunctor: instance Control.CatBifunctor.CatBiFunctor (,) (->)
- Control.CatBifunctor: instance Control.Comonad.Comonad m => Control.CatBifunctor.CatBiFunctor (,) (Control.Comonad.Cokleisli m)
- Control.CatBifunctor: instance GHC.Base.Monad m => Control.CatBifunctor.CatBiFunctor (,) (Control.Arrow.Kleisli m)
- Control.CatBifunctor: instance GHC.Base.Monad m => Control.CatBifunctor.CatBiFunctor Data.Either.Either (Control.Arrow.Kleisli m)
- Control.CatBifunctor: second :: CatBiFunctor p cat => cat a b -> cat (p c a) (p c b)
- Debug.LoggingBackprop: (*) :: forall x m. (Show x, Additive x, Multiplicative x, MonadLogger m) => Backprop (Kleisli m) (x, x) x
- Debug.LoggingBackprop: (+) :: forall x m. (Show x, Additive x, MonadLogger m) => Backprop (Kleisli m) (x, x) x
- Debug.LoggingBackprop: backpropExpr :: String -> BackpropFunc SimpleExpr SimpleExpr
- Debug.LoggingBackprop: const :: forall c x m. (Additive c, Additive x, Show c, Show x, Monad m) => c -> Backprop (Kleisli m) x c
- Debug.LoggingBackprop: cos :: forall x m. (Show x, TrigField x, MonadLogger m) => Backprop (Kleisli m) x x
- Debug.LoggingBackprop: exp :: forall x m. (ExpField x, Show x, MonadLogger m) => Backprop (Kleisli m) x x
- Debug.LoggingBackprop: initBinaryFunc :: (Show a, Show b, Show c, MonadLogger m) => String -> (a -> b -> c) -> Kleisli m (a, b) c
- Debug.LoggingBackprop: initUnaryFunc :: (Show a, Show b, MonadLogger m) => String -> (a -> b) -> Kleisli m a b
- Debug.LoggingBackprop: linear :: forall x m. (Show x, Distributive x, MonadLogger m) => x -> Backprop (Kleisli m) x x
- Debug.LoggingBackprop: loggingBackpropExpr :: forall m. MonadLogger m => String -> Backprop (Kleisli m) SimpleExpr SimpleExpr
- Debug.LoggingBackprop: negate :: forall x m. (Show x, Subtractive x, MonadLogger m) => Backprop (Kleisli m) x x
- Debug.LoggingBackprop: pow :: forall x m. (Show x, Divisive x, Distributive x, Subtractive x, FromIntegral x Integer, MonadLogger m) => Integer -> Backprop (Kleisli m) x x
- Debug.LoggingBackprop: pureKleisli :: Monad m => (a -> b) -> Kleisli m a b
- Debug.LoggingBackprop: sin :: forall x m. (Show x, TrigField x, MonadLogger m) => Backprop (Kleisli m) x x
- Debug.LoggingBackprop: unitConst :: (Show a, MonadLogger m) => a -> Kleisli m () a
- InfBackprop: (*) :: Distributive x => BackpropFunc (x, x) x
- InfBackprop: (**) :: forall a. (ExpField a, FromIntegral a Integer) => BackpropFunc (a, a) a
- InfBackprop: (***) :: CatBiFunctor p cat => cat a1 b1 -> cat a2 b2 -> cat (p a1 a2) (p b1 b2)
- InfBackprop: (+) :: forall x. Additive x => BackpropFunc (x, x) x
- InfBackprop: (-) :: forall x. Subtractive x => BackpropFunc (x, x) x
- InfBackprop: (/) :: forall x. (Divisive x, Distributive x, Subtractive x) => BackpropFunc (x, x) x
- InfBackprop: MkBackprop :: cat input output -> Backprop cat input (output, cache) -> Backprop cat (output, cache) input -> Backprop cat input output
- InfBackprop: acos :: (TrigField x, ExpField x) => BackpropFunc x x
- InfBackprop: acosh :: (TrigField x, ExpField x) => BackpropFunc x x
- InfBackprop: asin :: (TrigField x, ExpField x) => BackpropFunc x x
- InfBackprop: asinh :: (TrigField x, ExpField x) => BackpropFunc x x
- InfBackprop: atan :: TrigField x => BackpropFunc x x
- InfBackprop: atan2 :: TrigField a => BackpropFunc (a, a) a
- InfBackprop: atanh :: TrigField x => BackpropFunc x x
- InfBackprop: backpropExpr :: String -> BackpropFunc SimpleExpr SimpleExpr
- InfBackprop: backward :: Backprop cat input output -> Backprop cat (output, cache) input
- InfBackprop: call :: Backprop cat input output -> cat input output
- InfBackprop: const :: forall c x. (Additive c, Additive x) => c -> BackpropFunc x c
- InfBackprop: cos :: TrigField x => BackpropFunc x x
- InfBackprop: cosh :: TrigField x => BackpropFunc x x
- InfBackprop: data Backprop cat input output
- InfBackprop: derivative :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat y) => Backprop cat x y -> cat x x
- InfBackprop: derivativeN :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat x) => Natural -> Backprop cat x x -> cat x x
- InfBackprop: dup :: forall x. Additive x => BackpropFunc x (x, x)
- InfBackprop: exp :: forall x. ExpField x => BackpropFunc x x
- InfBackprop: first :: CatBiFunctor p cat => cat a b -> cat (p a c) (p b c)
- InfBackprop: forget :: forall x. Additive x => BackpropFunc x ()
- InfBackprop: forgetFirst :: forall x y. Additive x => BackpropFunc (x, y) y
- InfBackprop: forgetSecond :: forall x y. Additive y => BackpropFunc (x, y) x
- InfBackprop: forward :: Backprop cat input output -> Backprop cat input (output, cache)
- InfBackprop: linear :: forall x. Distributive x => x -> BackpropFunc x x
- InfBackprop: log :: ExpField x => BackpropFunc x x
- InfBackprop: logBase :: ExpField a => BackpropFunc (a, a) a
- InfBackprop: loggingBackpropExpr :: forall m. MonadLogger m => String -> Backprop (Kleisli m) SimpleExpr SimpleExpr
- InfBackprop: negate :: forall x. Subtractive x => BackpropFunc x x
- InfBackprop: pow :: forall x. (Divisive x, Distributive x, Subtractive x, FromIntegral x Integer) => Integer -> BackpropFunc x x
- InfBackprop: pureBackprop :: forall a b m. Monad m => Backprop (->) a b -> Backprop (Kleisli m) a b
- InfBackprop: pureKleisli :: Monad m => (a -> b) -> Kleisli m a b
- InfBackprop: second :: CatBiFunctor p cat => cat a b -> cat (p c a) (p c b)
- InfBackprop: setFirst :: forall x y c. Additive c => c -> BackpropFunc (c, x) y -> BackpropFunc x y
- InfBackprop: setSecond :: forall x y c. Additive c => c -> BackpropFunc (x, c) y -> BackpropFunc x y
- InfBackprop: simpleDifferentiable :: forall x. Distributive x => (x -> x) -> BackpropFunc x x -> BackpropFunc x x
- InfBackprop: sin :: TrigField x => BackpropFunc x x
- InfBackprop: sinh :: TrigField x => BackpropFunc x x
- InfBackprop: tan :: TrigField x => BackpropFunc x x
- InfBackprop: tanh :: TrigField x => BackpropFunc x x
- InfBackprop: type BackpropFunc = Backprop (->)
- InfBackprop.Common: MkBackprop :: cat input output -> Backprop cat input (output, cache) -> Backprop cat (output, cache) input -> Backprop cat input output
- InfBackprop.Common: backward :: Backprop cat input output -> Backprop cat (output, cache) input
- InfBackprop.Common: call :: Backprop cat input output -> cat input output
- InfBackprop.Common: class Distributive x => StartBackprop cat x
- InfBackprop.Common: const :: forall c x. (Additive c, Additive x) => c -> BackpropFunc x c
- InfBackprop.Common: data Backprop cat input output
- InfBackprop.Common: derivative :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat y) => Backprop cat x y -> cat x x
- InfBackprop.Common: derivativeN :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat x) => Natural -> Backprop cat x x -> cat x x
- InfBackprop.Common: forward :: Backprop cat input output -> Backprop cat input (output, cache)
- InfBackprop.Common: forwardBackward :: (Isomorphism cat, CatBiFunctor (,) cat) => Backprop cat y y -> Backprop cat x y -> Backprop cat x x
- InfBackprop.Common: instance (IsomorphismClass.Isomorphism.Isomorphism cat, Control.CatBifunctor.CatBiFunctor (,) cat) => Control.CatBifunctor.CatBiFunctor (,) (InfBackprop.Common.Backprop cat)
- InfBackprop.Common: instance (IsomorphismClass.Isomorphism.Isomorphism cat, Control.CatBifunctor.CatBiFunctor (,) cat) => Control.Category.Category (InfBackprop.Common.Backprop cat)
- InfBackprop.Common: instance (IsomorphismClass.Isomorphism.Isomorphism cat, Control.CatBifunctor.CatBiFunctor (,) cat) => IsomorphismClass.Isomorphism.Isomorphism (InfBackprop.Common.Backprop cat)
- InfBackprop.Common: instance (NumHask.Algebra.Ring.Distributive x, GHC.Base.Monad m) => InfBackprop.Common.StartBackprop (Control.Arrow.Kleisli m) x
- InfBackprop.Common: instance NumHask.Algebra.Ring.Distributive x => InfBackprop.Common.StartBackprop (->) x
- InfBackprop.Common: numba :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat y) => Backprop cat x y -> Backprop cat x x
- InfBackprop.Common: numbaN :: (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat x) => Natural -> Backprop cat x x -> Backprop cat x x
- InfBackprop.Common: pureBackprop :: forall a b m. Monad m => Backprop (->) a b -> Backprop (Kleisli m) a b
- InfBackprop.Common: startBackprop :: StartBackprop cat x => Backprop cat x x
- InfBackprop.Common: type BackpropFunc = Backprop (->)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo ((), a) a
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo ((a, b), (c, d)) ((a, c), (b, d))
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo ((a, b), c) (a, (b, c))
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either (Data.Either.Either a b) (Data.Either.Either c d)) (Data.Either.Either (Data.Either.Either a c) (Data.Either.Either b d))
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either (Data.Either.Either a b) c) (Data.Either.Either a (Data.Either.Either b c))
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either Data.Void.Void a) a
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either a (Data.Either.Either b c)) (Data.Either.Either (Data.Either.Either a b) c)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either a Data.Void.Void) a
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (Data.Either.Either a b) (Data.Either.Either b a)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (a, ()) a
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (a, (b, c)) ((a, b), c)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo (a, b) (b, a)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo a ((), a)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo a (Data.Either.Either Data.Void.Void a)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo a (Data.Either.Either a Data.Void.Void)
- IsomorphismClass.Extra: instance IsomorphismClass.Classes.IsomorphicTo.IsomorphicTo a (a, ())
- IsomorphismClass.Isomorphism: class Isomorphism (c :: Type -> Type -> Type)
- IsomorphismClass.Isomorphism: instance Control.Comonad.Comonad w => IsomorphismClass.Isomorphism.Isomorphism (Control.Comonad.Cokleisli w)
- IsomorphismClass.Isomorphism: instance GHC.Base.Monad m => IsomorphismClass.Isomorphism.Isomorphism (Control.Arrow.Kleisli m)
- IsomorphismClass.Isomorphism: instance IsomorphismClass.Isomorphism.Isomorphism (->)
- IsomorphismClass.Isomorphism: iso :: (Isomorphism c, IsomorphicTo a b) => c a b
- NumHask.Extra: instance (NumHask.Algebra.Additive.Additive x, NumHask.Algebra.Additive.Additive y) => NumHask.Algebra.Additive.Additive (x, y)
- NumHask.Extra: instance (NumHask.Algebra.Additive.Additive x, NumHask.Algebra.Additive.Additive y, NumHask.Algebra.Additive.Additive z) => NumHask.Algebra.Additive.Additive (x, y, z)
- NumHask.Extra: instance (NumHask.Algebra.Additive.Additive x, NumHask.Algebra.Additive.Additive y, NumHask.Algebra.Additive.Additive z, NumHask.Algebra.Additive.Additive t) => NumHask.Algebra.Additive.Additive (x, y, z, t)
- NumHask.Extra: instance (NumHask.Algebra.Additive.Additive x, NumHask.Algebra.Additive.Additive y, NumHask.Algebra.Additive.Additive z, NumHask.Algebra.Additive.Additive t, NumHask.Algebra.Additive.Additive s) => NumHask.Algebra.Additive.Additive (x, y, z, t, s)
- NumHask.Extra: instance NumHask.Algebra.Additive.Additive ()
- Prelude.InfBackprop: (*) :: Distributive x => BackpropFunc (x, x) x
- Prelude.InfBackprop: (**) :: forall a. (ExpField a, FromIntegral a Integer) => BackpropFunc (a, a) a
- Prelude.InfBackprop: (+) :: forall x. Additive x => BackpropFunc (x, x) x
- Prelude.InfBackprop: (-) :: forall x. Subtractive x => BackpropFunc (x, x) x
- Prelude.InfBackprop: (/) :: forall x. (Divisive x, Distributive x, Subtractive x) => BackpropFunc (x, x) x
- Prelude.InfBackprop: acos :: (TrigField x, ExpField x) => BackpropFunc x x
- Prelude.InfBackprop: acosh :: (TrigField x, ExpField x) => BackpropFunc x x
- Prelude.InfBackprop: asin :: (TrigField x, ExpField x) => BackpropFunc x x
- Prelude.InfBackprop: asinh :: (TrigField x, ExpField x) => BackpropFunc x x
- Prelude.InfBackprop: atan :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: atan2 :: TrigField a => BackpropFunc (a, a) a
- Prelude.InfBackprop: atanh :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: cos :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: cosh :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: dup :: forall x. Additive x => BackpropFunc x (x, x)
- Prelude.InfBackprop: exp :: forall x. ExpField x => BackpropFunc x x
- Prelude.InfBackprop: forget :: forall x. Additive x => BackpropFunc x ()
- Prelude.InfBackprop: forgetFirst :: forall x y. Additive x => BackpropFunc (x, y) y
- Prelude.InfBackprop: forgetSecond :: forall x y. Additive y => BackpropFunc (x, y) x
- Prelude.InfBackprop: linear :: forall x. Distributive x => x -> BackpropFunc x x
- Prelude.InfBackprop: log :: ExpField x => BackpropFunc x x
- Prelude.InfBackprop: logBase :: ExpField a => BackpropFunc (a, a) a
- Prelude.InfBackprop: negate :: forall x. Subtractive x => BackpropFunc x x
- Prelude.InfBackprop: pow :: forall x. (Divisive x, Distributive x, Subtractive x, FromIntegral x Integer) => Integer -> BackpropFunc x x
- Prelude.InfBackprop: setFirst :: forall x y c. Additive c => c -> BackpropFunc (c, x) y -> BackpropFunc x y
- Prelude.InfBackprop: setSecond :: forall x y c. Additive c => c -> BackpropFunc (x, c) y -> BackpropFunc x y
- Prelude.InfBackprop: simpleDifferentiable :: forall x. Distributive x => (x -> x) -> BackpropFunc x x -> BackpropFunc x x
- Prelude.InfBackprop: sin :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: sinh :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: tan :: TrigField x => BackpropFunc x x
- Prelude.InfBackprop: tanh :: TrigField x => BackpropFunc x x
+ Data.FiniteSupportStream: MkFiniteSupportStream :: Vector a -> FiniteSupportStream a
+ Data.FiniteSupportStream: [toVector] :: FiniteSupportStream a -> Vector a
+ Data.FiniteSupportStream: cons :: a -> FiniteSupportStream a -> FiniteSupportStream a
+ Data.FiniteSupportStream: cons' :: (Additive a, Eq a) => a -> FiniteSupportStream a -> FiniteSupportStream a
+ Data.FiniteSupportStream: empty :: FiniteSupportStream a
+ Data.FiniteSupportStream: finiteSupportStreamBasis :: a -> a -> Natural -> FiniteSupportStream a
+ Data.FiniteSupportStream: finiteSupportStreamSum :: Additive a => FiniteSupportStream a -> a
+ Data.FiniteSupportStream: foldlWithStream :: Foldable t => (b -> a -> c -> b) -> b -> t a -> Stream c -> b
+ Data.FiniteSupportStream: foldlWithStream' :: Foldable t => (b -> a -> c -> b) -> b -> t a -> Stream c -> b
+ Data.FiniteSupportStream: fromTuple :: forall input (length :: Nat) a. IndexedListLiterals input length a => input -> FiniteSupportStream a
+ Data.FiniteSupportStream: head :: Additive a => FiniteSupportStream a -> a
+ Data.FiniteSupportStream: instance (Debug.SimpleExpr.Utils.Algebra.Convolution a b c, NumHask.Algebra.Additive.Additive c) => Debug.SimpleExpr.Utils.Algebra.Convolution (Data.FiniteSupportStream.FiniteSupportStream a) (Data.FiniteSupportStream.FiniteSupportStream b) c
+ Data.FiniteSupportStream: instance (Debug.SimpleExpr.Utils.Algebra.Convolution a b c, NumHask.Algebra.Additive.Additive c) => Debug.SimpleExpr.Utils.Algebra.Convolution (Data.FiniteSupportStream.FiniteSupportStream a) (Data.Stream.Stream b) c
+ Data.FiniteSupportStream: instance (Debug.SimpleExpr.Utils.Algebra.Convolution a b c, NumHask.Algebra.Additive.Additive c) => Debug.SimpleExpr.Utils.Algebra.Convolution (Data.Stream.Stream a) (Data.FiniteSupportStream.FiniteSupportStream b) c
+ Data.FiniteSupportStream: instance (GHC.Classes.Eq a, NumHask.Algebra.Additive.Additive a) => GHC.Classes.Eq (Data.FiniteSupportStream.FiniteSupportStream a)
+ Data.FiniteSupportStream: instance (GHC.Show.Show a, GHC.Classes.Eq a, NumHask.Algebra.Additive.Additive a) => GHC.Show.Show (Data.FiniteSupportStream.FiniteSupportStream a)
+ Data.FiniteSupportStream: instance Control.ExtendableMap.ExtandableMap a b c d => Control.ExtendableMap.ExtandableMap a b (Data.FiniteSupportStream.FiniteSupportStream c) (Data.FiniteSupportStream.FiniteSupportStream d)
+ Data.FiniteSupportStream: instance Data.Foldable.Foldable Data.FiniteSupportStream.FiniteSupportStream
+ Data.FiniteSupportStream: instance Debug.SimpleExpr.Utils.Algebra.AlgebraicPower b a => Debug.SimpleExpr.Utils.Algebra.AlgebraicPower b (Data.FiniteSupportStream.FiniteSupportStream a)
+ Data.FiniteSupportStream: instance Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction a b => Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction a (Data.FiniteSupportStream.FiniteSupportStream b)
+ Data.FiniteSupportStream: instance NumHask.Algebra.Additive.Additive a => NumHask.Algebra.Additive.Additive (Data.FiniteSupportStream.FiniteSupportStream a)
+ Data.FiniteSupportStream: instance NumHask.Algebra.Additive.Subtractive a => NumHask.Algebra.Additive.Subtractive (Data.FiniteSupportStream.FiniteSupportStream a)
+ Data.FiniteSupportStream: mkFiniteSupportStream' :: (Eq a, Additive a) => Vector a -> FiniteSupportStream a
+ Data.FiniteSupportStream: multiplicativeAction :: Multiplicative a => Stream a -> FiniteSupportStream a -> FiniteSupportStream a
+ Data.FiniteSupportStream: newtype FiniteSupportStream a
+ Data.FiniteSupportStream: null :: FiniteSupportStream a -> Bool
+ Data.FiniteSupportStream: optimize :: (Eq a, Additive a) => FiniteSupportStream a -> FiniteSupportStream a
+ Data.FiniteSupportStream: replicate :: Natural -> a -> FiniteSupportStream a
+ Data.FiniteSupportStream: replicate' :: (Additive a, Eq a) => Natural -> a -> FiniteSupportStream a
+ Data.FiniteSupportStream: singleton :: a -> FiniteSupportStream a
+ Data.FiniteSupportStream: singleton' :: (Additive a, Eq a) => a -> FiniteSupportStream a
+ Data.FiniteSupportStream: streamsConvolution :: Distributive a => Stream a -> FiniteSupportStream a -> a
+ Data.FiniteSupportStream: supportLength :: FiniteSupportStream a -> Natural
+ Data.FiniteSupportStream: tail :: FiniteSupportStream a -> FiniteSupportStream a
+ Data.FiniteSupportStream: takeArray :: Additive a => Natural -> FiniteSupportStream a -> Vector a
+ Data.FiniteSupportStream: takeList :: Additive a => Natural -> FiniteSupportStream a -> [a]
+ Data.FiniteSupportStream: toInfiniteList :: Additive a => FiniteSupportStream a -> [a]
+ Data.FiniteSupportStream: toList :: FiniteSupportStream a -> [a]
+ Data.FiniteSupportStream: unsafeFromList :: [a] -> FiniteSupportStream a
+ Data.FiniteSupportStream: unsafeMap :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b
+ Data.FiniteSupportStream: unsafeZip :: (Additive a, Additive b) => FiniteSupportStream a -> FiniteSupportStream b -> FiniteSupportStream (a, b)
+ Data.FiniteSupportStream: unsafeZipWith :: (a -> b -> c) -> (a -> c) -> (b -> c) -> FiniteSupportStream a -> FiniteSupportStream b -> FiniteSupportStream c
+ Debug.DiffExpr: binarySymbolicFunc :: BinarySymbolicFunc a => String -> a -> a -> a
+ Debug.DiffExpr: class BinarySymbolicFunc a
+ Debug.DiffExpr: class SymbolicFunc a
+ Debug.DiffExpr: instance (Debug.DiffExpr.BinarySymbolicFunc a, GHC.Show.Show a) => Debug.DiffExpr.BinarySymbolicFunc (Debug.SimpleExpr.Utils.Traced.Traced a)
+ Debug.DiffExpr: instance (Debug.DiffExpr.BinarySymbolicFunc a, NumHask.Algebra.Ring.Distributive a, NumHask.Algebra.Additive.Additive t) => Debug.DiffExpr.BinarySymbolicFunc (Numeric.InfBackprop.Core.RevDiff t a a)
+ Debug.DiffExpr: instance (Debug.DiffExpr.SymbolicFunc a, GHC.Show.Show a) => Debug.DiffExpr.SymbolicFunc (Debug.SimpleExpr.Utils.Traced.Traced a)
+ Debug.DiffExpr: instance (Debug.DiffExpr.SymbolicFunc a, NumHask.Algebra.Multiplicative.Multiplicative a) => Debug.DiffExpr.SymbolicFunc (Numeric.InfBackprop.Core.RevDiff t a a)
+ Debug.DiffExpr: instance Debug.DiffExpr.BinarySymbolicFunc Debug.SimpleExpr.Expr.SimpleExpr
+ Debug.DiffExpr: instance Debug.DiffExpr.SymbolicFunc Debug.SimpleExpr.Expr.SimpleExpr
+ Debug.DiffExpr: twoArgFunc :: String -> SimpleExpr -> SimpleExpr -> SimpleExpr
+ Debug.DiffExpr: type TSE = TracedSimpleExpr
+ Debug.DiffExpr: type TracedSimpleExpr = Traced SimpleExpr
+ Debug.DiffExpr: unarySymbolicFunc :: SymbolicFunc a => String -> a -> a
+ Numeric.InfBackprop: MkRevDiff :: c -> (b -> a) -> RevDiff a b c
+ Numeric.InfBackprop: [backprop] :: RevDiff a b c -> b -> a
+ Numeric.InfBackprop: [value] :: RevDiff a b c -> c
+ Numeric.InfBackprop: autoArg :: AutoDifferentiableArgument a => RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a
+ Numeric.InfBackprop: autoVal :: AutoDifferentiableValue a => a -> DerivativeValue a
+ Numeric.InfBackprop: boxedVectorArg :: forall b (n :: Nat) a c. (Additive b, KnownNat n) => RevDiff a (BoxedVector n b) (BoxedVector n c) -> BoxedVector n (RevDiff a b c)
+ Numeric.InfBackprop: boxedVectorArgDerivative :: forall (n :: Nat) b a. (KnownNat n, AutoDifferentiableValue b, Additive (CT a)) => (BoxedVector n (RevDiff' (BoxedVector n a) a) -> b) -> BoxedVector n a -> DerivativeValue b
+ Numeric.InfBackprop: boxedVectorVal :: forall b (n :: Nat) a c. Multiplicative b => BoxedVector n (RevDiff a b c) -> BoxedVector n a
+ Numeric.InfBackprop: boxedVectorValDerivative :: forall a c (n :: Nat) b d. (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> BoxedVector n (RevDiff b c d)) -> DerivativeArg a -> BoxedVector n b
+ Numeric.InfBackprop: call :: (RevDiff' a a -> RevDiff' a b) -> a -> b
+ Numeric.InfBackprop: constDiff :: Additive a => c -> RevDiff a b c
+ Numeric.InfBackprop: customArgDerivative :: AutoDifferentiableValue c => (RevDiff (CT a) (CT a) a -> b) -> (b -> c) -> a -> DerivativeValue c
+ Numeric.InfBackprop: customArgValDerivative :: (RevDiff (CT a) (CT a) a -> b) -> (c -> d) -> (b -> c) -> a -> d
+ Numeric.InfBackprop: customValDerivative :: (DerivativeRoot b ~ CT (DerivativeArg b), DerivativeCoarg b ~ CT (DerivativeArg b), AutoDifferentiableArgument b) => (c -> d) -> (b -> c) -> DerivativeArg b -> d
+ Numeric.InfBackprop: data RevDiff a b c
+ Numeric.InfBackprop: derivative3ArgsOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop: derivative3ArgsOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> RevDiff' a1 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop: derivative3ArgsOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => (RevDiff' a2 a0 -> RevDiff' a2 a1 -> RevDiff' a2 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop: derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a
+ Numeric.InfBackprop: finiteSupportStreamArg :: Additive b => RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream (RevDiff a b c)
+ Numeric.InfBackprop: finiteSupportStreamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) -> FiniteSupportStream a -> DerivativeValue b
+ Numeric.InfBackprop: finiteSupportStreamVal :: Multiplicative b => FiniteSupportStream (RevDiff a b c) -> FiniteSupportStream a
+ Numeric.InfBackprop: finiteSupportStreamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> FiniteSupportStream (RevDiff b c d)) -> DerivativeArg a -> FiniteSupportStream b
+ Numeric.InfBackprop: fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b
+ Numeric.InfBackprop: fromProfunctors :: (forall (p :: Type -> Type -> Type). Costrong p => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b
+ Numeric.InfBackprop: fromVanLaarhoven :: forall a b. (forall (f :: Type -> Type). Functor f => (b -> f (CT b)) -> a -> f (CT a)) -> DifferentiableFunc a b
+ Numeric.InfBackprop: initDiff :: a -> RevDiff b b a
+ Numeric.InfBackprop: maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c)
+ Numeric.InfBackprop: maybeArgDerivative :: AutoDifferentiableValue b => (Maybe (RevDiff' (Maybe a) a) -> b) -> Maybe a -> DerivativeValue b
+ Numeric.InfBackprop: maybeVal :: Multiplicative b => Maybe (RevDiff a b c) -> Maybe a
+ Numeric.InfBackprop: maybeValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Maybe (RevDiff b c d)) -> DerivativeArg a -> Maybe b
+ Numeric.InfBackprop: mkBoxedVectorArg :: forall b (n :: Nat) a c d. (Additive b, KnownNat n) => RevDiffArg a b c d -> RevDiffArg a (BoxedVector n b) (BoxedVector n c) (BoxedVector n d)
+ Numeric.InfBackprop: mkBoxedVectorVal :: forall a b (n :: Nat). (a -> b) -> BoxedVector n a -> BoxedVector n b
+ Numeric.InfBackprop: mkFiniteSupportStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream d
+ Numeric.InfBackprop: mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b
+ Numeric.InfBackprop: mkMaybeArg :: (RevDiff a b c -> d) -> RevDiff a (Maybe b) (Maybe c) -> Maybe d
+ Numeric.InfBackprop: mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b
+ Numeric.InfBackprop: mkStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (FiniteSupportStream b) (Stream c) -> Stream d
+ Numeric.InfBackprop: mkStreamVal :: (a -> b) -> Stream a -> Stream b
+ Numeric.InfBackprop: mkTripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a b2 c2 d2 -> RevDiffArg a (b0, b1, b2) (c0, c1, c2) (d0, d1, d2)
+ Numeric.InfBackprop: mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)
+ Numeric.InfBackprop: mkTupleArg :: (Additive b0, Additive b1) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a (b0, b1) (c0, c1) (d0, d1)
+ Numeric.InfBackprop: mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1)
+ Numeric.InfBackprop: scalarArg :: RevDiff a b c -> RevDiff a b c
+ Numeric.InfBackprop: scalarArgDerivative :: AutoDifferentiableValue c => (RevDiff' a a -> c) -> a -> DerivativeValue c
+ Numeric.InfBackprop: scalarVal :: Multiplicative b => RevDiff a b c -> a
+ Numeric.InfBackprop: scalarValDerivative :: (DerivativeRoot b ~ CT a, DerivativeCoarg b ~ CT a, DerivativeArg b ~ a, Multiplicative (CT c), AutoDifferentiableArgument b) => (b -> RevDiff d (CT c) c) -> a -> d
+ Numeric.InfBackprop: simpleDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> CT a
+ Numeric.InfBackprop: simpleDifferentiableFunc :: Multiplicative b => (b -> b) -> (b -> b) -> RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop: simpleValueAndDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> (b, CT a)
+ Numeric.InfBackprop: stopDiff :: StopDiff a b => a -> b
+ Numeric.InfBackprop: streamArg :: Additive b => RevDiff a (FiniteSupportStream b) (Stream c) -> Stream (RevDiff a b c)
+ Numeric.InfBackprop: streamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (Stream (RevDiff' (Stream a) a) -> b) -> Stream a -> DerivativeValue b
+ Numeric.InfBackprop: streamVal :: Multiplicative b => Stream (RevDiff a b c) -> Stream a
+ Numeric.InfBackprop: streamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Stream (RevDiff b c d)) -> DerivativeArg a -> Stream b
+ Numeric.InfBackprop: threeArgsDerivative :: (AutoDifferentiableValue b, Additive (CT a0), Additive (CT a1), Additive (CT a2)) => (RevDiff' (a0, a1, a2) a0 -> RevDiff' (a0, a1, a2) a1 -> RevDiff' (a0, a1, a2) a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop: threeArgsToTriple :: Additive a => RevDiff a b0 c0 -> RevDiff a b1 c1 -> RevDiff a b2 c2 -> RevDiff a (b0, b1, b2) (c0, c1, c2)
+ Numeric.InfBackprop: toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d
+ Numeric.InfBackprop: toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca)
+ Numeric.InfBackprop: toProfunctors :: Costrong p => DifferentiableFunc a b -> p (CT a) a -> p (CT b) b
+ Numeric.InfBackprop: toVanLaarhoven :: Functor f => DifferentiableFunc a b -> (b -> f (CT b)) -> a -> f (CT a)
+ Numeric.InfBackprop: tripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiff a (b0, b1, b2) (c0, c1, c2) -> (RevDiff a b0 c0, RevDiff a b1 c1, RevDiff a b2 c2)
+ Numeric.InfBackprop: tripleArgDerivative :: (Additive (CT a0), Additive (CT a1), Additive (CT a2), AutoDifferentiableValue b) => ((RevDiff' (a0, a1, a2) a0, RevDiff' (a0, a1, a2) a1, RevDiff' (a0, a1, a2) a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop: tripleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop: tripleDerivativeOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop: tripleDerivativeOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop: tripleVal :: (Multiplicative b0, Multiplicative b1, Multiplicative b2) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) -> (a0, a1, a2)
+ Numeric.InfBackprop: tripleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, Multiplicative c2, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1, RevDiff b2 c2 d2)) -> DerivativeArg a -> (b0, b1, b2)
+ Numeric.InfBackprop: tupleArg :: (Additive b0, Additive b1) => RevDiff a (b0, b1) (c0, c1) -> (RevDiff a b0 c0, RevDiff a b1 c1)
+ Numeric.InfBackprop: tupleArgDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop: tupleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop: tupleDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop: tupleVal :: (Multiplicative b0, Multiplicative b1) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1) -> (a0, a1)
+ Numeric.InfBackprop: tupleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1)) -> DerivativeArg a -> (b0, b1)
+ Numeric.InfBackprop: twoArgsDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop: twoArgsDerivativeOverX :: (Additive (CT a0), AutoDifferentiableValue b) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop: twoArgsDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop: type CT a = Cotangent a
+ Numeric.InfBackprop: type Cotangent a = Dual Tangent a
+ Numeric.InfBackprop: type DifferentiableFunc a b = forall t. () => RevDiff t CT a a -> RevDiff t CT b b
+ Numeric.InfBackprop: type RevDiff' a b = RevDiff CT a CT b b
+ Numeric.InfBackprop: type family Dual x
+ Numeric.InfBackprop.Core: MkRevDiff :: c -> (b -> a) -> RevDiff a b c
+ Numeric.InfBackprop.Core: [backprop] :: RevDiff a b c -> b -> a
+ Numeric.InfBackprop.Core: [value] :: RevDiff a b c -> c
+ Numeric.InfBackprop.Core: autoArg :: AutoDifferentiableArgument a => RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a
+ Numeric.InfBackprop.Core: autoVal :: AutoDifferentiableValue a => a -> DerivativeValue a
+ Numeric.InfBackprop.Core: boxedVectorArg :: forall b (n :: Nat) a c. (Additive b, KnownNat n) => RevDiff a (BoxedVector n b) (BoxedVector n c) -> BoxedVector n (RevDiff a b c)
+ Numeric.InfBackprop.Core: boxedVectorArgDerivative :: forall (n :: Nat) b a. (KnownNat n, AutoDifferentiableValue b, Additive (CT a)) => (BoxedVector n (RevDiff' (BoxedVector n a) a) -> b) -> BoxedVector n a -> DerivativeValue b
+ Numeric.InfBackprop.Core: boxedVectorVal :: forall b (n :: Nat) a c. Multiplicative b => BoxedVector n (RevDiff a b c) -> BoxedVector n a
+ Numeric.InfBackprop.Core: boxedVectorValDerivative :: forall a c (n :: Nat) b d. (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> BoxedVector n (RevDiff b c d)) -> DerivativeArg a -> BoxedVector n b
+ Numeric.InfBackprop.Core: call :: (RevDiff' a a -> RevDiff' a b) -> a -> b
+ Numeric.InfBackprop.Core: class (Additive DerivativeRoot a, Additive DerivativeCoarg a) => AutoDifferentiableArgument a
+ Numeric.InfBackprop.Core: class AutoDifferentiableValue a
+ Numeric.InfBackprop.Core: class HasConstant a b c d
+ Numeric.InfBackprop.Core: class StopDiff a b
+ Numeric.InfBackprop.Core: constDiff :: Additive a => c -> RevDiff a b c
+ Numeric.InfBackprop.Core: constant :: HasConstant a b c d => Proxy a -> b -> c -> d
+ Numeric.InfBackprop.Core: customArgDerivative :: AutoDifferentiableValue c => (RevDiff (CT a) (CT a) a -> b) -> (b -> c) -> a -> DerivativeValue c
+ Numeric.InfBackprop.Core: customArgValDerivative :: (RevDiff (CT a) (CT a) a -> b) -> (c -> d) -> (b -> c) -> a -> d
+ Numeric.InfBackprop.Core: customValDerivative :: (DerivativeRoot b ~ CT (DerivativeArg b), DerivativeCoarg b ~ CT (DerivativeArg b), AutoDifferentiableArgument b) => (c -> d) -> (b -> c) -> DerivativeArg b -> d
+ Numeric.InfBackprop.Core: data RevDiff a b c
+ Numeric.InfBackprop.Core: derivative3ArgsOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop.Core: derivative3ArgsOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> RevDiff' a1 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop.Core: derivative3ArgsOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => (RevDiff' a2 a0 -> RevDiff' a2 a1 -> RevDiff' a2 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop.Core: derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a
+ Numeric.InfBackprop.Core: differentiableAcos :: (TrigField b, ExpField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAcosh :: (TrigField b, ExpField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAsin :: (TrigField b, ExpField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAsinh :: (TrigField b, ExpField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAtan :: (TrigField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAtan2 :: (TrigField b, IntegerPower b) => RevDiff a (b, b) (b, b) -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableAtanh :: (TrigField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableConv :: (Convolution a b c, Convolution cc b ca, Convolution a cc cb) => RevDiff ct (ca, cb) (a, b) -> RevDiff ct cc c
+ Numeric.InfBackprop.Core: differentiableCos :: TrigField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableCosh :: TrigField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableDiv :: (Subtractive b, Divisive b) => RevDiff a (b, b) (b, b) -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableExp :: ExpField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableLog :: ExpField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableLogBase :: (ExpField b, IntegerPower b) => RevDiff a (b, b) (b, b) -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableMult :: Multiplicative b => RevDiff a (b, b) (b, b) -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableMultAction :: (MultiplicativeAction a b, MultiplicativeAction a cb, Convolution b cb ca) => RevDiff ct (ca, cb) (a, b) -> RevDiff ct cb b
+ Numeric.InfBackprop.Core: differentiableNegate :: (Subtractive a, Subtractive c) => RevDiff a b c -> RevDiff a b c
+ Numeric.InfBackprop.Core: differentiablePow :: ExpField b => RevDiff a (b, b) (b, b) -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableRecip :: (Divisive b, Subtractive b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableSin :: TrigField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableSinh :: TrigField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableSqrt :: ExpField b => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableSub :: (Subtractive b, Subtractive c) => RevDiff a (b, b) (c, c) -> RevDiff a b c
+ Numeric.InfBackprop.Core: differentiableSum :: Additive c => RevDiff a (b, b) (c, c) -> RevDiff a b c
+ Numeric.InfBackprop.Core: differentiableTan :: (TrigField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: differentiableTanh :: (TrigField b, IntegerPower b) => RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: finiteSupportStreamArg :: Additive b => RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream (RevDiff a b c)
+ Numeric.InfBackprop.Core: finiteSupportStreamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) -> FiniteSupportStream a -> DerivativeValue b
+ Numeric.InfBackprop.Core: finiteSupportStreamVal :: Multiplicative b => FiniteSupportStream (RevDiff a b c) -> FiniteSupportStream a
+ Numeric.InfBackprop.Core: finiteSupportStreamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> FiniteSupportStream (RevDiff b c d)) -> DerivativeArg a -> FiniteSupportStream b
+ Numeric.InfBackprop.Core: fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b
+ Numeric.InfBackprop.Core: fromProfunctors :: (forall (p :: Type -> Type -> Type). Costrong p => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b
+ Numeric.InfBackprop.Core: fromVanLaarhoven :: forall a b. (forall (f :: Type -> Type). Functor f => (b -> f (CT b)) -> a -> f (CT a)) -> DifferentiableFunc a b
+ Numeric.InfBackprop.Core: initDiff :: a -> RevDiff b b a
+ Numeric.InfBackprop.Core: instance (Debug.SimpleExpr.Utils.Algebra.AlgebraicPower GHC.Num.Integer.Integer a, Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction GHC.Num.Integer.Integer a, NumHask.Algebra.Multiplicative.Multiplicative a) => Debug.SimpleExpr.Utils.Algebra.AlgebraicPower GHC.Num.Integer.Integer (Numeric.InfBackprop.Core.RevDiff c a a)
+ Numeric.InfBackprop.Core: instance (Debug.SimpleExpr.Utils.Algebra.AlgebraicPower GHC.Types.Int a, Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction GHC.Types.Int a, NumHask.Algebra.Multiplicative.Multiplicative a) => Debug.SimpleExpr.Utils.Algebra.AlgebraicPower GHC.Types.Int (Numeric.InfBackprop.Core.RevDiff c a a)
+ Numeric.InfBackprop.Core: instance (Debug.SimpleExpr.Utils.Algebra.Convolution a b c, Debug.SimpleExpr.Utils.Algebra.Convolution cc b ca, Debug.SimpleExpr.Utils.Algebra.Convolution a cc cb, NumHask.Algebra.Additive.Additive ct) => Debug.SimpleExpr.Utils.Algebra.Convolution (Numeric.InfBackprop.Core.RevDiff ct ca a) (Numeric.InfBackprop.Core.RevDiff ct cb b) (Numeric.InfBackprop.Core.RevDiff ct cc c)
+ Numeric.InfBackprop.Core: instance (Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction GHC.Num.Integer.Integer b, Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction GHC.Num.Integer.Integer cb) => Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction GHC.Num.Integer.Integer (Numeric.InfBackprop.Core.RevDiff ct cb b)
+ Numeric.InfBackprop.Core: instance (Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction a b, Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction a cb, Debug.SimpleExpr.Utils.Algebra.Convolution b cb ca, NumHask.Algebra.Additive.Additive ct) => Debug.SimpleExpr.Utils.Algebra.MultiplicativeAction (Numeric.InfBackprop.Core.RevDiff ct ca a) (Numeric.InfBackprop.Core.RevDiff ct cb b)
+ Numeric.InfBackprop.Core: instance (GHC.Show.Show (b -> a), GHC.Show.Show c) => GHC.Show.Show (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Additive b) => Numeric.InfBackprop.Core.AutoDifferentiableArgument (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Additive c) => NumHask.Algebra.Additive.Additive (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Subtractive a, GHC.Num.Num b, NumHask.Algebra.Additive.Subtractive b, NumHask.Algebra.Multiplicative.Multiplicative b) => GHC.Num.Num (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Subtractive a, NumHask.Algebra.Additive.Subtractive b, NumHask.Algebra.Additive.Subtractive c) => NumHask.Algebra.Additive.Subtractive (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Subtractive a, NumHask.Algebra.Additive.Subtractive b, NumHask.Algebra.Multiplicative.Divisive b, GHC.Real.Fractional b, Debug.SimpleExpr.Utils.Algebra.IntegerPower b) => GHC.Real.Fractional (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Subtractive a, NumHask.Algebra.Field.ExpField b, NumHask.Algebra.Field.TrigField b, Debug.SimpleExpr.Utils.Algebra.IntegerPower b) => NumHask.Algebra.Field.TrigField (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Multiplicative.Divisive b, NumHask.Algebra.Additive.Subtractive b, Debug.SimpleExpr.Utils.Algebra.IntegerPower b) => NumHask.Algebra.Multiplicative.Divisive (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Multiplicative.Multiplicative b) => NumHask.Algebra.Multiplicative.Multiplicative (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Algebra.Field.ExpField b, NumHask.Algebra.Additive.Additive a, NumHask.Algebra.Additive.Subtractive a, Debug.SimpleExpr.Utils.Algebra.IntegerPower b) => NumHask.Algebra.Field.ExpField (Numeric.InfBackprop.Core.RevDiff a b b)
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromInteger c, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromInteger (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Int.Int16, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Int.Int16
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Int.Int32, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Int.Int32
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Int.Int64, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Int.Int64
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Int.Int8, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Int.Int8
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Num.Integer.Integer, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Num.Integer.Integer
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Num.Natural.Natural, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Num.Natural.Natural
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Types.Int, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Types.Int
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Types.Word, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Types.Word
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Word.Word16, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Word.Word16
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Word.Word32, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Word.Word32
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Word.Word64, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Word.Word64
+ Numeric.InfBackprop.Core: instance (NumHask.Data.Integral.FromIntegral c GHC.Word.Word8, NumHask.Algebra.Additive.Additive a) => NumHask.Data.Integral.FromIntegral (Numeric.InfBackprop.Core.RevDiff a b c) GHC.Word.Word8
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.AutoDifferentiableArgument a, GHC.TypeNats.KnownNat n) => Numeric.InfBackprop.Core.AutoDifferentiableArgument (Numeric.InfBackprop.Utils.SizedVector.BoxedVector n a)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.AutoDifferentiableArgument a0, Numeric.InfBackprop.Core.AutoDifferentiableArgument a1, Numeric.InfBackprop.Core.AutoDifferentiableArgument a2, Numeric.InfBackprop.Core.DerivativeRoot a0 GHC.Types.~ Numeric.InfBackprop.Core.DerivativeRoot a1, Numeric.InfBackprop.Core.DerivativeRoot a0 GHC.Types.~ Numeric.InfBackprop.Core.DerivativeRoot a2) => Numeric.InfBackprop.Core.AutoDifferentiableArgument (a0, a1, a2)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.AutoDifferentiableArgument a0, Numeric.InfBackprop.Core.AutoDifferentiableArgument a1, Numeric.InfBackprop.Core.DerivativeRoot a0 GHC.Types.~ Numeric.InfBackprop.Core.DerivativeRoot a1) => Numeric.InfBackprop.Core.AutoDifferentiableArgument (a0, a1)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.AutoDifferentiableValue a0, Numeric.InfBackprop.Core.AutoDifferentiableValue a1) => Numeric.InfBackprop.Core.AutoDifferentiableValue (a0, a1)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.AutoDifferentiableValue a0, Numeric.InfBackprop.Core.AutoDifferentiableValue a1, Numeric.InfBackprop.Core.AutoDifferentiableValue a2) => Numeric.InfBackprop.Core.AutoDifferentiableValue (a0, a1, a2)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.HasConstant a b c d, NumHask.Algebra.Additive.Additive t, e GHC.Types.~ Numeric.InfBackprop.Core.CT c, f GHC.Types.~ Numeric.InfBackprop.Core.CT d) => Numeric.InfBackprop.Core.HasConstant a b (Numeric.InfBackprop.Core.RevDiff t e c) (Numeric.InfBackprop.Core.RevDiff t f d)
+ Numeric.InfBackprop.Core: instance (Numeric.InfBackprop.Core.StopDiff a d, NumHask.Algebra.Additive.Additive b) => Numeric.InfBackprop.Core.StopDiff a (Numeric.InfBackprop.Core.RevDiff b c d)
+ Numeric.InfBackprop.Core: instance Data.Profunctor.Strong.Costrong (Numeric.InfBackprop.Core.RevDiff t)
+ Numeric.InfBackprop.Core: instance Data.Profunctor.Unsafe.Profunctor (Numeric.InfBackprop.Core.RevDiff t)
+ Numeric.InfBackprop.Core: instance GHC.Generics.Generic (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance NumHask.Algebra.Multiplicative.Multiplicative b => Numeric.InfBackprop.Core.AutoDifferentiableValue (Numeric.InfBackprop.Core.RevDiff a b c)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableArgument a => Numeric.InfBackprop.Core.AutoDifferentiableArgument (Data.FiniteSupportStream.FiniteSupportStream a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableArgument a => Numeric.InfBackprop.Core.AutoDifferentiableArgument (Data.Stream.Stream a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableArgument a => Numeric.InfBackprop.Core.AutoDifferentiableArgument (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableValue a => Numeric.InfBackprop.Core.AutoDifferentiableValue (Data.FiniteSupportStream.FiniteSupportStream a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableValue a => Numeric.InfBackprop.Core.AutoDifferentiableValue (Data.Stream.Stream a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableValue a => Numeric.InfBackprop.Core.AutoDifferentiableValue (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.AutoDifferentiableValue a => Numeric.InfBackprop.Core.AutoDifferentiableValue (Numeric.InfBackprop.Utils.SizedVector.BoxedVector n a)
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.HasConstant a b a b
+ Numeric.InfBackprop.Core: instance Numeric.InfBackprop.Core.StopDiff a a
+ Numeric.InfBackprop.Core: maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c)
+ Numeric.InfBackprop.Core: maybeArgDerivative :: AutoDifferentiableValue b => (Maybe (RevDiff' (Maybe a) a) -> b) -> Maybe a -> DerivativeValue b
+ Numeric.InfBackprop.Core: maybeVal :: Multiplicative b => Maybe (RevDiff a b c) -> Maybe a
+ Numeric.InfBackprop.Core: maybeValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Maybe (RevDiff b c d)) -> DerivativeArg a -> Maybe b
+ Numeric.InfBackprop.Core: mkBoxedVectorArg :: forall b (n :: Nat) a c d. (Additive b, KnownNat n) => RevDiffArg a b c d -> RevDiffArg a (BoxedVector n b) (BoxedVector n c) (BoxedVector n d)
+ Numeric.InfBackprop.Core: mkBoxedVectorVal :: forall a b (n :: Nat). (a -> b) -> BoxedVector n a -> BoxedVector n b
+ Numeric.InfBackprop.Core: mkFiniteSupportStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream d
+ Numeric.InfBackprop.Core: mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b
+ Numeric.InfBackprop.Core: mkMaybeArg :: (RevDiff a b c -> d) -> RevDiff a (Maybe b) (Maybe c) -> Maybe d
+ Numeric.InfBackprop.Core: mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b
+ Numeric.InfBackprop.Core: mkStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (FiniteSupportStream b) (Stream c) -> Stream d
+ Numeric.InfBackprop.Core: mkStreamVal :: (a -> b) -> Stream a -> Stream b
+ Numeric.InfBackprop.Core: mkTripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a b2 c2 d2 -> RevDiffArg a (b0, b1, b2) (c0, c1, c2) (d0, d1, d2)
+ Numeric.InfBackprop.Core: mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)
+ Numeric.InfBackprop.Core: mkTupleArg :: (Additive b0, Additive b1) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a (b0, b1) (c0, c1) (d0, d1)
+ Numeric.InfBackprop.Core: mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1)
+ Numeric.InfBackprop.Core: sameTypeDerivative :: Multiplicative (CT a) => (RevDiff (CT a) (CT a) a -> RevDiff (CT a) (CT a) a) -> a -> CT a
+ Numeric.InfBackprop.Core: scalarArg :: RevDiff a b c -> RevDiff a b c
+ Numeric.InfBackprop.Core: scalarArgDerivative :: AutoDifferentiableValue c => (RevDiff' a a -> c) -> a -> DerivativeValue c
+ Numeric.InfBackprop.Core: scalarVal :: Multiplicative b => RevDiff a b c -> a
+ Numeric.InfBackprop.Core: scalarValDerivative :: (DerivativeRoot b ~ CT a, DerivativeCoarg b ~ CT a, DerivativeArg b ~ a, Multiplicative (CT c), AutoDifferentiableArgument b) => (b -> RevDiff d (CT c) c) -> a -> d
+ Numeric.InfBackprop.Core: simpleDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> CT a
+ Numeric.InfBackprop.Core: simpleDifferentiableFunc :: Multiplicative b => (b -> b) -> (b -> b) -> RevDiff a b b -> RevDiff a b b
+ Numeric.InfBackprop.Core: simpleValueAndDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> (b, CT a)
+ Numeric.InfBackprop.Core: stopDiff :: StopDiff a b => a -> b
+ Numeric.InfBackprop.Core: streamArg :: Additive b => RevDiff a (FiniteSupportStream b) (Stream c) -> Stream (RevDiff a b c)
+ Numeric.InfBackprop.Core: streamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (Stream (RevDiff' (Stream a) a) -> b) -> Stream a -> DerivativeValue b
+ Numeric.InfBackprop.Core: streamVal :: Multiplicative b => Stream (RevDiff a b c) -> Stream a
+ Numeric.InfBackprop.Core: streamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Stream (RevDiff b c d)) -> DerivativeArg a -> Stream b
+ Numeric.InfBackprop.Core: threeArgsDerivative :: (AutoDifferentiableValue b, Additive (CT a0), Additive (CT a1), Additive (CT a2)) => (RevDiff' (a0, a1, a2) a0 -> RevDiff' (a0, a1, a2) a1 -> RevDiff' (a0, a1, a2) a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
+ Numeric.InfBackprop.Core: threeArgsToTriple :: Additive a => RevDiff a b0 c0 -> RevDiff a b1 c1 -> RevDiff a b2 c2 -> RevDiff a (b0, b1, b2) (c0, c1, c2)
+ Numeric.InfBackprop.Core: toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d
+ Numeric.InfBackprop.Core: toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca)
+ Numeric.InfBackprop.Core: toProfunctors :: Costrong p => DifferentiableFunc a b -> p (CT a) a -> p (CT b) b
+ Numeric.InfBackprop.Core: toVanLaarhoven :: Functor f => DifferentiableFunc a b -> (b -> f (CT b)) -> a -> f (CT a)
+ Numeric.InfBackprop.Core: tripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiff a (b0, b1, b2) (c0, c1, c2) -> (RevDiff a b0 c0, RevDiff a b1 c1, RevDiff a b2 c2)
+ Numeric.InfBackprop.Core: tripleArgDerivative :: (Additive (CT a0), Additive (CT a1), Additive (CT a2), AutoDifferentiableValue b) => ((RevDiff' (a0, a1, a2) a0, RevDiff' (a0, a1, a2) a1, RevDiff' (a0, a1, a2) a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tripleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tripleDerivativeOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tripleDerivativeOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tripleVal :: (Multiplicative b0, Multiplicative b1, Multiplicative b2) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) -> (a0, a1, a2)
+ Numeric.InfBackprop.Core: tripleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, Multiplicative c2, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1, RevDiff b2 c2 d2)) -> DerivativeArg a -> (b0, b1, b2)
+ Numeric.InfBackprop.Core: tupleArg :: (Additive b0, Additive b1) => RevDiff a (b0, b1) (c0, c1) -> (RevDiff a b0 c0, RevDiff a b1 c1)
+ Numeric.InfBackprop.Core: tupleArgDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tupleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tupleDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) -> (a0, a1) -> DerivativeValue b
+ Numeric.InfBackprop.Core: tupleVal :: (Multiplicative b0, Multiplicative b1) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1) -> (a0, a1)
+ Numeric.InfBackprop.Core: tupleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1)) -> DerivativeArg a -> (b0, b1)
+ Numeric.InfBackprop.Core: twoArgsDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop.Core: twoArgsDerivativeOverX :: (Additive (CT a0), AutoDifferentiableValue b) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop.Core: twoArgsDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) -> a0 -> a1 -> DerivativeValue b
+ Numeric.InfBackprop.Core: type CT a = Cotangent a
+ Numeric.InfBackprop.Core: type Cotangent a = Dual Tangent a
+ Numeric.InfBackprop.Core: type DifferentiableFunc a b = forall t. () => RevDiff t CT a a -> RevDiff t CT b b
+ Numeric.InfBackprop.Core: type RevDiff' a b = RevDiff CT a CT b b
+ Numeric.InfBackprop.Core: type family DerivativeValue a
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Additive.Additive a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Additive.Additive (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Additive.Subtractive a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Additive.Subtractive (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Field.ExpField a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Field.ExpField (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Field.TrigField a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Field.TrigField (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Multiplicative.Divisive a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Multiplicative.Divisive (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (GHC.TypeNats.KnownNat n, NumHask.Algebra.Multiplicative.Multiplicative a, Data.Vector.Generic.Base.Vector v a) => NumHask.Algebra.Multiplicative.Multiplicative (Data.Vector.Generic.Sized.Internal.Vector v n a)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Additive.Additive a0, NumHask.Algebra.Additive.Additive a1) => NumHask.Algebra.Additive.Additive (a0, a1)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Additive.Additive a0, NumHask.Algebra.Additive.Additive a1, NumHask.Algebra.Additive.Additive a2) => NumHask.Algebra.Additive.Additive (a0, a1, a2)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Additive.Subtractive a0, NumHask.Algebra.Additive.Subtractive a1) => NumHask.Algebra.Additive.Subtractive (a0, a1)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Additive.Subtractive a0, NumHask.Algebra.Additive.Subtractive a1, NumHask.Algebra.Additive.Subtractive a2) => NumHask.Algebra.Additive.Subtractive (a0, a1, a2)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Field.ExpField a, NumHask.Algebra.Field.ExpField b) => NumHask.Algebra.Field.ExpField (a, b)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Field.ExpField a0, NumHask.Algebra.Field.ExpField a1, NumHask.Algebra.Field.ExpField a2) => NumHask.Algebra.Field.ExpField (a0, a1, a2)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Field.TrigField a, NumHask.Algebra.Field.TrigField b) => NumHask.Algebra.Field.TrigField (a, b)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Field.TrigField a, NumHask.Algebra.Field.TrigField b, NumHask.Algebra.Field.TrigField c) => NumHask.Algebra.Field.TrigField (a, b, c)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Multiplicative.Divisive a0, NumHask.Algebra.Multiplicative.Divisive a1) => NumHask.Algebra.Multiplicative.Divisive (a0, a1)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Multiplicative.Divisive a0, NumHask.Algebra.Multiplicative.Divisive a1, NumHask.Algebra.Multiplicative.Divisive a2) => NumHask.Algebra.Multiplicative.Divisive (a0, a1, a2)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Multiplicative.Multiplicative a0, NumHask.Algebra.Multiplicative.Multiplicative a1) => NumHask.Algebra.Multiplicative.Multiplicative (a0, a1)
+ Numeric.InfBackprop.Instances.NumHask: instance (NumHask.Algebra.Multiplicative.Multiplicative a0, NumHask.Algebra.Multiplicative.Multiplicative a1, NumHask.Algebra.Multiplicative.Multiplicative a2) => NumHask.Algebra.Multiplicative.Multiplicative (a0, a1, a2)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Additive.Additive a => NumHask.Algebra.Additive.Additive (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Additive.Additive a => NumHask.Algebra.Additive.Additive (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Additive.Subtractive a => NumHask.Algebra.Additive.Subtractive (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Additive.Subtractive a => NumHask.Algebra.Additive.Subtractive (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Field.ExpField a => NumHask.Algebra.Field.ExpField (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Field.ExpField a => NumHask.Algebra.Field.ExpField (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Field.TrigField a => NumHask.Algebra.Field.TrigField (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Field.TrigField a => NumHask.Algebra.Field.TrigField (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Multiplicative.Divisive a => NumHask.Algebra.Multiplicative.Divisive (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Multiplicative.Divisive a => NumHask.Algebra.Multiplicative.Divisive (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Multiplicative.Multiplicative a => NumHask.Algebra.Multiplicative.Multiplicative (Data.Stream.Stream a)
+ Numeric.InfBackprop.Instances.NumHask: instance NumHask.Algebra.Multiplicative.Multiplicative a => NumHask.Algebra.Multiplicative.Multiplicative (GHC.Maybe.Maybe a)
+ Numeric.InfBackprop.Utils.SizedVector: boxedVectorBasis :: forall (v :: Type -> Type) a (n :: Nat). (Vector v a, KnownNat n) => Finite n -> a -> a -> Vector v n a
+ Numeric.InfBackprop.Utils.SizedVector: boxedVectorSum :: forall a (n :: Nat). Additive a => Vector Vector n a -> a
+ Numeric.InfBackprop.Utils.SizedVector: type BoxedVector (n :: Nat) a = Vector Vector n a
+ Numeric.InfBackprop.Utils.Tuple: biCross :: (a -> b -> c) -> (d -> e -> f) -> (a, d) -> (b, e) -> (c, f)
+ Numeric.InfBackprop.Utils.Tuple: biCross3 :: (a -> b -> c) -> (d -> e -> f) -> (g -> h -> l) -> (a, d, g) -> (b, e, h) -> (c, f, l)
+ Numeric.InfBackprop.Utils.Tuple: cross :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)
+ Numeric.InfBackprop.Utils.Tuple: cross3 :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)
+ Numeric.InfBackprop.Utils.Tuple: curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
+ Numeric.InfBackprop.Utils.Tuple: fork :: (t -> a) -> (t -> b) -> t -> (a, b)
+ Numeric.InfBackprop.Utils.Tuple: fork3 :: (t -> a0) -> (t -> a1) -> (t -> a2) -> t -> (a0, a1, a2)
+ Numeric.InfBackprop.Utils.Tuple: uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
+ Numeric.InfBackprop.Utils.Vector: fromTuple :: forall v a input (length :: Nat). (Vector v a, IndexedListLiterals input length a) => input -> v a
+ Numeric.InfBackprop.Utils.Vector: safeHead :: (Vector v a, MonadPlus m) => v a -> m a
+ Numeric.InfBackprop.Utils.Vector: safeLast :: (Vector v a, MonadPlus m) => v a -> m a
+ Numeric.InfBackprop.Utils.Vector: trimArrayHead :: (Vector v a, Eq a) => a -> v a -> v a
+ Numeric.InfBackprop.Utils.Vector: trimArrayTail :: (Vector v a, Eq a) => a -> v a -> v a
+ Numeric.InfBackprop.Utils.Vector: zipWith :: (Vector v a, Vector v b, Vector v c) => (a -> b -> c) -> (a -> c) -> (b -> c) -> v a -> v b -> v c

Files

CHANGELOG.md view
@@ -1,9 +1,37 @@-# Revision history for simple-expr+# Revision history for inf-backprop +## 0.2.0.0 -- 2025-11-13++### Major Breaking Changes++* **Complete rewrite**: +The entire codebase has been rewritten from scratch with a redesigned architecture. +* Differentiation can now be applied to ordinary functions through the `RevDiff` type, +* rather than requiring special function wrappers.++### New Features++* **Core automatic differentiation**:+  * `RevDiff` type for reverse-mode automatic differentiation+  * Typeclass instances for `RevDiff`+  * Support for higher-order derivatives through the derivative operator composition++* **NumHask integration**:+  * Orphan instances for NumHask typeclasses, providing polymorphic numeric operations++* **Utility modules**:+  * Sized vectors+  * Tuple and triple manipulation utilities for multi-argument functions+  * Vector utilities++* **Documentation**:+  * Comprehensive tutorial introducing core concepts and usage patterns+ ## 0.1.0.0 -- 2023-05-12  * Basic types `Backprop`, `StartBackprop` etc. * Basic function backprrop derivative implementations.-* `Isomorphism` tyepclass and extra instances for `IsomorphicTo` typeclass from `isomorphism-class` package.+* `Isomorphism` tyepclass and extra instances for `IsomorphicTo` typeclass +from `isomorphism-class` package. * Extra instancies for `Additive` typeclass from `numhask` package.  * Tutorial
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2023, Alexey Tochin+Copyright (c) 2023-2025, Alexey Tochin  All rights reserved. 
+ doc/images/backprop.drawio.png view

binary file changed (absent → 34215 bytes)

+ doc/images/backprop.png view

binary file changed (absent → 18174 bytes)

doc/images/composition_derivative.png view

binary file changed (21314 → 21434 bytes)

doc/images/composition_second_derivative.png view

binary file changed (52118 → 52301 bytes)

+ doc/images/lens.drawio.png view

binary file changed (absent → 14390 bytes)

+ doc/images/lens.png view

binary file changed (absent → 6948 bytes)

doctests/Main.hs view
@@ -18,5 +18,9 @@       "-XTupleSections",       "-XFlexibleContexts",       "-XDeriveFunctor",+      "-XBangPatterns",+      "-XDataKinds",+      "-XTypeApplications",+      "-XTypeOperators",       "src"     ]
inf-backprop.cabal view
@@ -5,43 +5,72 @@ -- see: https://github.com/sol/hpack  name:           inf-backprop-version:        0.1.1.0+version:        0.2.0.0 synopsis:       Automatic differentiation and backpropagation.-description:    ![Second order derivative of a composition](docs/doc/images/composition_second_derivative.png)+description:    ![Second order derivative of a composition](docs/doc/images/composition_second_derivative.png)                  .-                Automatic differentiation and backpropagation.-                We do not attract gradient tape.-                Instead, the differentiation operator is defined directly as a map between differentiable function objects.-                Such functions are to be combined in arrow style using '(>>>)', '(***)', 'first', etc.+                 Automatic differentiation library with efficient reverse-mode backpropagation for Haskell.                  .-                The original purpose of the package is an automatic backpropagation differentiation component-                for a functional type-dependent library for deep machine learning.-                See [tutorial](docs/InfBackprop-Tutorial.html) details.+                 This package provides a general-purpose automatic differentiation system designed for building strongly typed deep learning frameworks. It offers: +                .+                 * Reverse-mode automatic differentiation (backpropagation) +                .+                 * Support for higher-order derivatives +                .+                 * Type-safe gradient computation +                .+                 * Integration with [numhask](https://hackage.haskell.org/package/numhask) +                .+                 * Flexible representations including profunctor and Van Laarhoven encodings +                .+                 The library emphasizes composability and type safety, making it suitable+                for research, prototyping neural networks, and implementing custom+                differentiable algorithms. +                .+                 See the [tutorial](docs/Numeric-InfBackprop-Tutorial.html) for detailed+                examples and usage patterns. +                .+                 Similar Projects: +                .+                 * [ad](https://hackage.haskell.org/package/ad) - Comprehensive automatic differentiation library supporting forward and reverse modes +                .+                 * [backprop](https://hackage.haskell.org/package/backprop) - Heterogeneous automatic differentiation with emphasis on ease of use category:       Mathematics author:         Alexey Tochin maintainer:     Alexey.Tochin@gmail.com-copyright:      2023 Alexey Tochin+copyright:      2023-2025 Alexey Tochin license:        BSD3 license-file:   LICENSE build-type:     Simple extra-source-files:     CHANGELOG.md+    doc/images/backprop.drawio.png+    doc/images/backprop.png+    doc/images/composition.png+    doc/images/composition_derivative.png+    doc/images/composition_second_derivative.png+    doc/images/lens.drawio.png+    doc/images/lens.png extra-doc-files:+    doc/images/backprop.drawio.png+    doc/images/backprop.png     doc/images/composition.png     doc/images/composition_derivative.png     doc/images/composition_second_derivative.png+    doc/images/lens.drawio.png+    doc/images/lens.png  library   exposed-modules:-      Control.CatBifunctor-      Debug.LoggingBackprop-      InfBackprop-      InfBackprop.Common-      InfBackprop.Tutorial-      IsomorphismClass.Extra-      IsomorphismClass.Isomorphism-      NumHask.Extra-      Prelude.InfBackprop+      Data.FiniteSupportStream+      Debug.DiffExpr+      Numeric.InfBackprop+      Numeric.InfBackprop.Core+      Numeric.InfBackprop.Instances.NumHask+      Numeric.InfBackprop.Tutorial+      Numeric.InfBackprop.Utils.SizedVector+      Numeric.InfBackprop.Utils.Tuple+      Numeric.InfBackprop.Utils.Vector   other-modules:       Paths_inf_backprop   hs-source-dirs:@@ -59,16 +88,39 @@       TupleSections       FlexibleContexts       DeriveFunctor+      TypeOperators+      TypeApplications+      BangPatterns+      DataKinds+      PatternSynonyms   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints   build-depends:-      base >=4.7 && <5-    , comonad-    , isomorphism-class-    , monad-logger-    , numhask-    , simple-expr-    , text-    , transformers+      Stream <0.5+    , base >=4.7 && <5+    , combinatorial <0.2+    , comonad <5.1+    , composition <1.1+    , data-fix <0.4+    , deepseq <1.6+    , extra <1.9+    , finite-typelits <0.3+    , fixed-vector <2.1+    , ghc-prim <0.13+    , hashable <1.6+    , indexed-list-literals <0.3+    , isomorphism-class <0.4+    , lens <5.4+    , numhask <0.14+    , optics <0.5+    , primitive <0.10+    , profunctors <5.7+    , safe <0.4+    , simple-expr <0.3+    , text <2.2+    , transformers <0.7+    , unordered-containers <0.3+    , vector <0.14+    , vector-sized <1.7   default-language: Haskell2010  test-suite doctests@@ -78,15 +130,33 @@       Paths_inf_backprop   hs-source-dirs:       doctests-  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -w -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base >=4.7 && <5+      Stream+    , base >=4.7 && <5+    , combinatorial     , comonad+    , composition+    , data-fix+    , deepseq     , doctest+    , extra+    , finite-typelits+    , fixed-vector+    , ghc-prim+    , hashable+    , indexed-list-literals     , isomorphism-class-    , monad-logger+    , lens     , numhask-    , simple-expr+    , optics+    , primitive+    , profunctors+    , safe+    , simple-expr ==0.2.*     , text     , transformers+    , unordered-containers+    , vector+    , vector-sized   default-language: Haskell2010
− src/Control/CatBifunctor.hs
@@ -1,179 +0,0 @@-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  Control.CatBifunctor--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Categorical Bifunctor typeclass and its trivial instances.-module Control.CatBifunctor-  ( CatBiFunctor,-    first,-    second,-    (***),-  )-where--import Control.Applicative (liftA2)-import Control.Arrow (Kleisli (Kleisli), (>>>))-import Control.Category (Category, id)-import Control.Comonad (Cokleisli (Cokleisli), Comonad, liftW)-import Data.Bifunctor (bimap)-import GHC.Base (Type)-import Prelude (Either (Left, Right), Monad, fmap, fst, snd, ($))---- | Categorical generalization for bifunctor with arrow notations.--- Notice that we do NOT require the categorical morphism '(>>>)'--- and morphism tensor product '(***)' are interchangeable. Namely,------ @ (f >>> g) *** (h >>> l) != (f *** h) >>> (g *** l) @------ in general.------ ==== __Monad and type product instance examples of usage __------ >>> import Prelude (Int, pure, Maybe(Just, Nothing), const, replicate, String)--- >>> import Control.Arrow (Kleisli(Kleisli), runKleisli)------ >>> runKleisli (Kleisli pure *** Kleisli pure) (1,2) :: [(Int, Int)]--- [(1,2)]------ >>> runKleisli (Kleisli pure *** Kleisli pure) (1,2) :: Maybe (Int, Int)--- Just (1,2)------ >>> runKleisli (Kleisli pure *** Kleisli (const Nothing)) (1,2) :: Maybe (Int, Int)--- Nothing------ >>> runKleisli (Kleisli (replicate 2) *** Kleisli (replicate 3)) ("a","b") :: [(String, String)]--- [("a","b"),("a","b"),("a","b"),("a","b"),("a","b"),("a","b")]------ ==== __Comonad and type product instance examples of usage__------ >>> import Prelude (Int, pure, Maybe(..), const, replicate, String, (+), (++), Functor, Show, show, (==), (-))--- >>> import Control.Comonad (Cokleisli(Cokleisli), runCokleisli, extract, duplicate, (=>=))--- >>> import Control.Comonad.Store (store, seek, runStore, Store, StoreT)--- >>> import Control.Category ((>>>))------ >>> runCokleisli (Cokleisli extract *** Cokleisli extract) (store (\x -> (x + 1, x + 2)) 3) :: (Int, Int)--- (4,5)------ >>> :{--- up :: Int -> Cokleisli (Store Int) Int Int--- up n = Cokleisli $ \st -> let (ws, s) = runStore st in ws (s + n)--- :}------ >>> runCokleisli ((up 3 *** up 5) >>> (up 2 *** up 4)) (store (\x -> (x + 1, x + 2)) 0) :: (Int, Int)--- (6,11)------ >>> runCokleisli ((up 3 >>> up 2) *** (up 5 >>> up 4)) (store (\x -> (x + 1, x + 2)) 0) :: (Int, Int)--- (6,11)------ >>> :{--- data Stream a = Cons a (Stream a)--- tail :: Stream a -> Stream a--- tail (Cons _ xs) = xs--- instance Show a => Show (Stream a) where---   show (Cons x0 (Cons x1 (Cons x2 (Cons x3 (Cons x4 _))))) = show [x0, x1, x2, x3, x4] ++ "..."--- instance Functor Stream where---   fmap f (Cons x xs) = Cons (f x) (fmap f xs)--- instance Comonad Stream where---   extract (Cons x _ ) = x---   duplicate xs = Cons xs (duplicate (tail xs))--- :}------ >>> :{--- dup :: a -> (a, a)--- dup x = (x, x)--- naturals :: Int -> Stream Int--- naturals n = Cons n (naturals (n + 1))--- take :: Int -> Stream a -> a--- take n (Cons x xs) = if n == 0---   then x---   else take (n - 1) xs--- :}------ >>> naturals 0--- [0,1,2,3,4]...------ >>> take 5 (naturals 0)--- 5------ >>> ((take 3) =>= (take 4)) (naturals 0)--- 7------ >>> runCokleisli (Cokleisli (take 3) *** Cokleisli (take 4)) (fmap dup (naturals 0)) :: (Int, Int)--- (3,4)------ >>> streamN n = Cokleisli (take n)------ >>> runCokleisli ((streamN 3 *** streamN 5) >>> (streamN 2 *** streamN 4)) (fmap dup (naturals 0)) :: (Int, Int)--- (5,9)------ >>> runCokleisli ((streamN 3 >>> streamN 2) *** (streamN 5 >>> streamN 4)) (fmap dup (naturals 0)) :: (Int, Int)--- (5,9)------ ==== __Monad and type sum examples of usage__------ >>> import Prelude (Int, pure, Maybe(Just, Nothing), const, replicate, String)--- >>> import Control.Arrow (Kleisli(Kleisli), runKleisli)------ >>> runKleisli (Kleisli pure *** Kleisli pure) (Left "a") :: [Either String Int]--- [Left "a"]------ >>> runKleisli (Kleisli pure *** Kleisli pure) (Right 1) :: Maybe (Either String Int)--- Just (Right 1)-class-  Category cat =>-  CatBiFunctor (p :: Type -> Type -> Type) (cat :: Type -> Type -> Type)-  where-  -- | Categorical generalization of-  ---  -- @bimap :: (a1 -> b1) -> (a2 -> b2) -> (p a1 a2 -> p c1 c2)@-  ---  -- borrowed from arrows.-  (***) :: cat a1 b1 -> cat a2 b2 -> cat (p a1 a2) (p b1 b2)--  -- | Categorical generalization of-  ---  -- @first :: (a -> b) -> (p a c -> p c b)@-  ---  -- borrowed from arrows.-  first :: cat a b -> cat (p a c) (p b c)-  first f = f *** id--  -- | Categorical generalization of-  ---  -- @second :: (a -> b) -> (p a c -> p c b)@-  ---  -- borrowed from arrows.-  second :: cat a b -> cat (p c a) (p c b)-  second f = id *** f--instance CatBiFunctor (,) (->) where-  first f = bimap f id-  second = bimap id-  (***) = bimap--instance forall m. Monad m => CatBiFunctor (,) (Kleisli m) where-  (***) :: Kleisli m a1 b1 -> Kleisli m a2 b2 -> Kleisli m (a1, a2) (b1, b2)-  (Kleisli (mf1 :: a1 -> m b1)) *** (Kleisli (mf2 :: a2 -> m b2)) = Kleisli mf12-    where-      mf12 :: (a1, a2) -> m (b1, b2)-      mf12 (x1, x2) = liftA2 (,) (mf1 x1) (mf2 x2)--instance forall m. Comonad m => CatBiFunctor (,) (Cokleisli m) where-  (***) :: Cokleisli m a1 b1 -> Cokleisli m a2 b2 -> Cokleisli m (a1, a2) (b1, b2)-  (Cokleisli (mf1 :: m a1 -> b1)) *** (Cokleisli (mf2 :: m a2 -> b2)) = Cokleisli mf12-    where-      mf12 :: m (a1, a2) -> (b1, b2)-      mf12 x12 = (mf1 $ liftW fst x12, mf2 $ liftW snd x12)--instance forall m. Monad m => CatBiFunctor Either (Kleisli m) where-  (***) :: Kleisli m a1 b1 -> Kleisli m a2 b2 -> Kleisli m (Either a1 a2) (Either b1 b2)-  (Kleisli (mf1 :: a1 -> m b1)) *** (Kleisli (mf2 :: a2 -> m b2)) = Kleisli mf12-    where-      mf12 :: Either a1 a2 -> m (Either b1 b2)-      mf12 x12 = case x12 of-        Left x1 -> fmap Left (mf1 x1)-        Right x2 -> fmap Right (mf2 x2)
+ src/Data/FiniteSupportStream.hs view
@@ -0,0 +1,692 @@+{-# LANGUAGE DeriveFoldable #-}++-- | Module    :  Data.FiniteSupportStream+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- This module provides functionality for working with infinite streams that have+-- finite support (i.e., only finitely many non-zero elements). The streams are+-- internally represented as arrays for efficient computation.+--+-- Any linear functional on an ordinary stream ('Data.Stream.Stream')+-- can be represented as a finite support stream.+-- Inversely, any finite support stream can be represented as+-- a linear functional on an ordinary stream.+module Data.FiniteSupportStream+  ( -- * The type of finite support streams+    FiniteSupportStream (toVector, MkFiniteSupportStream),++    -- * Basic functions+    supportLength,+    null,+    head,+    tail,+    cons,+    cons',+    streamsConvolution,+    finiteSupportStreamSum,+    unsafeMap,++    -- * Transformations+    optimize,+    unsafeZip,+    unsafeZipWith,++    -- * Construction+    mkFiniteSupportStream',+    empty,+    singleton,+    singleton',+    replicate,+    replicate',+    unsafeFromList,+    fromTuple,+    finiteSupportStreamBasis,++    -- * Conversion+    multiplicativeAction,+    takeArray,+    takeList,+    toList,+    toInfiniteList,++    -- * Fold tools+    foldlWithStream,+    foldlWithStream',+  )+where++import Control.ExtendableMap (ExtandableMap, extendMap)+import Data.Eq ((==))+import Data.Foldable (Foldable, foldl')+import qualified Data.IndexedListLiterals as DILL+import Data.List (repeat, (++))+import qualified Data.List as DL+import Data.Maybe (fromMaybe)+import Data.Monoid (mconcat)+import qualified Data.Stream as DS+import Data.Tuple (fst)+import Data.Vector (Vector)+import qualified Data.Vector as DV+import Debug.SimpleExpr.Utils.Algebra+  ( AlgebraicPower ((^^)),+    Convolution ((|*|)),+    MultiplicativeAction ((*|)),+  )+import GHC.Base (Bool, Eq, fmap, id, ($), (.), (<>), (>))+import GHC.Natural (Natural)+import GHC.Real (fromIntegral)+import GHC.Show (Show, show)+import NumHask+  ( Additive,+    Distributive,+    Multiplicative,+    Subtractive,+    negate,+    zero,+    (*),+    (+),+    (-),+  )+import qualified NumHask+import Numeric.InfBackprop.Instances.NumHask ()+import Numeric.InfBackprop.Utils.Vector (safeHead, trimArrayTail)+import qualified Numeric.InfBackprop.Utils.Vector as DVIBP++-- | A stream with finite support, represented as a vector.+-- Elements beyond the vector's length are implicitly zero.+-- The vector may contain trailing zeros, which can be removed using 'optimize'.+--+-- The type parameter @a@ typically has an 'Additive' instance with a zero element.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int, Float, Bool(False, True))+-- >>> import Data.Vector (fromList)+--+-- >>> MkFiniteSupportStream $ fromList [0, 1, 2, 3] :: FiniteSupportStream Int+-- [0,1,2,3,0,0,0,...+--+-- >>> MkFiniteSupportStream $ fromList [0, 1, 2, 3] :: FiniteSupportStream Float+-- [0.0,1.0,2.0,3.0,0.0,0.0,0.0,...+--+-- >>> MkFiniteSupportStream $ fromList [False, True] :: FiniteSupportStream Bool+-- [False,True,False,False,False,...+newtype FiniteSupportStream a = MkFiniteSupportStream {toVector :: DV.Vector a}+  deriving (Foldable)++-- | Lifts a function to work with finite support streams.+-- This function applies the provided function to each element of the stream support.+-- The function is usafe because it is not checked that the argument function+-- maps zero to zero, which is expected.+--+-- ==== __Examples__+--+-- >>> unsafeMap (*2) (MkFiniteSupportStream $ DV.fromList [0, 1, 2, 3])+-- [0,2,4,6,0,0,0,...+--+-- >>> unsafeMap (+1) (MkFiniteSupportStream $ DV.fromList [0, 1, 2, 3])+-- [1,2,3,4,0,0,0,...+unsafeMap :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b+unsafeMap f (MkFiniteSupportStream array') = MkFiniteSupportStream $ DV.map f array'++-- | `Eq` instance of `FiniteSupportStream`.+instance (Eq a, Additive a) => Eq (FiniteSupportStream a) where+  x == y = x' == y'+    where+      x' = toVector $ optimize x+      y' = toVector $ optimize y++-- | `Show` instance of `FiniteSupportStream`.+instance forall a. (Show a, Eq a, Additive a) => Show (FiniteSupportStream a) where+  show bs =+    let (MkFiniteSupportStream array') = optimize bs+     in "["+          <> mconcat (fmap (\x -> show x <> ",") (DV.toList array' ++ [zero, zero, zero]))+          <> "..."++-- | `Additive` instance for `FiniteSupportStream`.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> (unsafeFromList [1, 2, 3]) + (unsafeFromList [10, 20]) :: FiniteSupportStream Int+-- [11,22,3,0,0,0,...+--+-- >>> (unsafeFromList [1, 2, 3]) + empty+-- [1,2,3,0,0,0,...+instance (Additive a) => Additive (FiniteSupportStream a) where+  zero = empty+  (MkFiniteSupportStream a0) + (MkFiniteSupportStream a1) =+    MkFiniteSupportStream $+      DVIBP.zipWith (+) id id a0 a1++-- | `Subtractive` instance for `FiniteSupportStream`.+--+-- ==== __Examples__+--+-- >>> unsafeFromList [10, 20, 30] - unsafeFromList [1, 2]+-- [9,18,30,0,0,0,...+--+-- >>> unsafeFromList [1, 2, 3] - unsafeFromList [1, 2, 3]+-- [0,0,0,...+instance (Subtractive a) => Subtractive (FiniteSupportStream a) where+  negate = unsafeMap negate+  (MkFiniteSupportStream a0) - (MkFiniteSupportStream a1) =+    MkFiniteSupportStream $+      DVIBP.zipWith (-) id negate a0 a1++-- | `FiniteSupportStream` instance of `MultiplicativeAction`.+instance+  (MultiplicativeAction a b) =>+  MultiplicativeAction a (FiniteSupportStream b)+  where+  (*|) = unsafeMap . (*|)++-- | `FiniteSupportStream`instance of `AlgebraicPower` typeclass+-- for raising `FiniteSupportStream` to powers.+instance+  (AlgebraicPower b a) =>+  AlgebraicPower b (FiniteSupportStream a)+  where+  x ^^ n = unsafeMap (^^ n) x++-- | `FiniteSupportStream` instance of 'ExtandableMap' typeclass.+instance+  (ExtandableMap a b c d) =>+  ExtandableMap a b (FiniteSupportStream c) (FiniteSupportStream d)+  where+  extendMap = unsafeMap . extendMap++-- | `Convolution` instance for `FiniteSupportStream` and `Data.Stream.Stream`.+instance+  (Convolution a b c, Additive c) =>+  Convolution (FiniteSupportStream a) (DS.Stream b) c+  where+  fss |*| s = foldlWithStream' (\acc x y -> acc + x |*| y) zero fss s++-- | `Convolution` instance for `Data.Stream.Stream` and `FiniteSupportStream`.+instance+  (Convolution a b c, Additive c) =>+  Convolution (DS.Stream a) (FiniteSupportStream b) c+  where+  s |*| fss = foldlWithStream' (\acc x y -> acc + y |*| x) zero fss s++-- | `Convolution` instance for `FiniteSupportStream` and `FiniteSupportStream`.+instance+  (Convolution a b c, Additive c) =>+  Convolution (FiniteSupportStream a) (FiniteSupportStream b) c+  where+  (MkFiniteSupportStream vx) |*| (MkFiniteSupportStream vy) = vx |*| vy++-- | Creates a finite support stream from a array, removing trailing zeros in the tail.+-- This is a constructor that ensures the minimal representation.+--+-- ==== __Examples__+--+-- >>> import Data.Vector (fromList)+--+-- >>> toVector $ mkFiniteSupportStream' $ fromList [0, 1, 2, 3, 0]+-- [0,1,2,3]+mkFiniteSupportStream' :: (Eq a, Additive a) => DV.Vector a -> FiniteSupportStream a+mkFiniteSupportStream' array' = MkFiniteSupportStream $ trimArrayTail zero array'++-- | Removes trailing elements of the finite support stream's inner array+-- if they are zeros.+-- The resulting stream is represented in its minimal form.+--+-- ==== __Examples__+--+-- >>> optimize $ unsafeFromList [0, 1, 0, 3, 0, 0]+-- [0,1,0,3,0,0,0,...+optimize :: (Eq a, Additive a) => FiniteSupportStream a -> FiniteSupportStream a+optimize (MkFiniteSupportStream array') = mkFiniteSupportStream' array'++-- | Returns the length of the stream's support (the vector length after optimization).+-- Trailing zeros are not counted in the support length.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> supportLength $ unsafeFromList [0, 1, 2, 3]+-- 4+--+-- >>> supportLength $ unsafeFromList [0, 1, 2, 3, 0, 0]+-- 6+supportLength :: FiniteSupportStream a -> Natural+supportLength = fromIntegral . DV.length . toVector++-- | Checks if the finite support stream is empty.+--+-- ==== __Examples__+--+-- >>> null $ unsafeFromList [0, 1, 2]+-- False+--+-- >>> null $ unsafeFromList []+-- True+--+-- >>> null $ unsafeFromList [0, 0, 0]+-- False+null :: FiniteSupportStream a -> Bool+null = DV.null . toVector++-- | Converts a finite list to a 'FiniteSupportStream'.+-- The list is assumed to be finite.+-- Trailing zero elements are not checked, and the inner array is not trimmed.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int, Float, Bool(False, True))+--+-- >>> unsafeFromList [0, 1, 2, 3] :: FiniteSupportStream Int+-- [0,1,2,3,0,0,0,...+--+-- >>> unsafeFromList [0, 1, 2, 3] :: FiniteSupportStream Float+-- [0.0,1.0,2.0,3.0,0.0,0.0,0.0,...+--+-- >>> unsafeFromList [False, True]+-- [False,True,False,False,False,...+unsafeFromList :: [a] -> FiniteSupportStream a+unsafeFromList = MkFiniteSupportStream . DV.fromList++-- | Converts a tuple into a `FiniteSupportStream`.+-- Trailing zero elements are not checked, and the inner array is not trimmed.+--+-- === __Examples__+--+-- >>> import GHC.Base (Int, Float, Bool(False, True))+-- >>> import GHC.Integer (Integer)+--+-- >>> fromTuple (0, 1, 2, 3) :: FiniteSupportStream Integer+-- [0,1,2,3,0,0,0,...+--+-- >>> fromTuple (0 :: Float, 1 :: Float, 2 :: Float, 3 :: Float) :: FiniteSupportStream Float+-- [0.0,1.0,2.0,3.0,0.0,0.0,0.0,...+--+-- >>> fromTuple (False, True) :: FiniteSupportStream Bool+-- [False,True,False,False,False,...+fromTuple ::+  (DILL.IndexedListLiterals input length a) =>+  input ->+  FiniteSupportStream a+fromTuple = MkFiniteSupportStream . DV.fromList . DILL.toList++-- | Converts a finite support stream to a finite list.+-- The resulting list includes all elements of the stream, including any trailing zeros.+--+-- ==== __Examples__+--+-- >>> toList $ unsafeFromList [1, 2, 3]+-- [1,2,3]+--+-- >>> toList $ unsafeFromList [1, 2, 3, 0]+-- [1,2,3,0]+toList :: FiniteSupportStream a -> [a]+toList = DV.toList . toVector++-- | Converts a finite support stream to an infinite list.+-- The resulting list contains all elements of the stream, followed by an infinite sequence of zeros.+--+-- ==== __Examples__+--+-- >>> import Data.List (take)+--+-- >>> take 5 $ toInfiniteList $ unsafeFromList [1, 2, 3]+-- [1,2,3,0,0]+toInfiniteList :: (Additive a) => FiniteSupportStream a -> [a]+toInfiniteList fss = toList fss ++ repeat zero++-- | Empty finite support stream.+-- The stream contains only zeros.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int, Bool)+--+-- >>> empty :: FiniteSupportStream Int+-- [0,0,0,...+--+-- >>> empty :: FiniteSupportStream Bool+-- [False,False,False,...+empty :: FiniteSupportStream a+empty = MkFiniteSupportStream DV.empty++-- | Returns the first element of the finite support stream.+-- If the stream is empty, it returns 'zero'.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int, Bool)+--+-- >>> head $ unsafeFromList [1, 2, 3]+-- 1+--+-- >>> head $ empty :: Int+-- 0+--+-- >>> head $ empty :: Bool+-- False+head :: (Additive a) => FiniteSupportStream a -> a+head (MkFiniteSupportStream array') = fromMaybe zero (safeHead array')++-- | Removes the first element of the finite support stream.+-- If the stream is empty, it returns an empty stream.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> tail $ unsafeFromList [1, 2, 3]+-- [2,3,0,0,0,...+--+-- >>> tail $ empty :: FiniteSupportStream Int+-- [0,0,0,...+tail :: FiniteSupportStream a -> FiniteSupportStream a+tail (MkFiniteSupportStream array') =+  if DV.null array'+    then empty+    else MkFiniteSupportStream $ DV.tail array'++-- | Takes the first @n@ elements of the finite support stream in the form of an array.+-- If @n@ is greater than the length of the stream, the result is padded with zeros.+-- The resulting array is not trimmed.+--+-- ==== __Examples__+--+-- >>> takeArray 5 $ unsafeFromList [1, 2, 3]+-- [1,2,3,0,0]+takeArray :: (Additive a) => Natural -> FiniteSupportStream a -> Vector a+takeArray n (MkFiniteSupportStream array) =+  if fromIntegral n > DV.length array+    then array <> DV.replicate (fromIntegral n - DV.length array) zero+    else DV.slice 0 (fromIntegral n) array++-- | Takes the first @n@ elements of the finite support stream in the form of a list.+-- If @n@ is greater than the length of the stream, the result is padded with zeros.+--+-- ==== __Examples__+--+-- >>> takeList 5 $ unsafeFromList [1, 2, 3]+-- [1,2,3,0,0]+takeList :: (Additive a) => Natural -> FiniteSupportStream a -> [a]+takeList n fss = DV.toList $ takeArray n fss++-- | Creates a finite support stream with exactly one element.+-- The element is not checked for being zero.+--+-- ==== __Examples__+--+-- >>> toVector $ singleton 42+-- [42]+--+-- >>> toVector $ singleton 0+-- [0]+--+-- >>> singleton 42+-- [42,0,0,0,...+--+-- >>> singleton 0+-- [0,0,0,...+--+-- >>> toVector $ singleton "a"+-- ["a"]+singleton :: a -> FiniteSupportStream a+singleton = MkFiniteSupportStream . DV.singleton++-- | Creates a finite support stream with exactly one non-zero element+-- if the provided element is not zero.+-- Returns the empty stream otherwise.+--+-- ==== __Examples__+--+-- >>> toVector $ singleton' 42+-- [42]+--+-- >>> toVector $ singleton' 0+-- []+--+-- >>> singleton' 42+-- [42,0,0,0,...+--+-- >>> singleton' 0+-- [0,0,0,...+singleton' :: (Additive a, Eq a) => a -> FiniteSupportStream a+singleton' x =+  if x == zero+    then empty+    else MkFiniteSupportStream $ DV.singleton x++-- | Creates a finite support stream with a constant value along the support.+-- It does not check whether the provided value is zero.+-- In this case, the inner array contains only zeros.+--+-- ==== __Examples__+--+-- >>> replicate 3 42+-- [42,42,42,0,0,0,...+--+-- >>> replicate 2 0+-- [0,0,0,...+--+-- >>> toVector $ replicate 2 0+-- [0,0]+replicate :: Natural -> a -> FiniteSupportStream a+replicate n x = MkFiniteSupportStream $ DV.replicate (fromIntegral n) x++-- | Creates a finite support stream with a constant value along the support.+-- It checks whether the provided value is zero.+-- In this case, the inner array is empty.+--+-- ==== __Examples__+--+-- >>> replicate' 3 42+-- [42,42,42,0,0,0,...+--+-- >>> replicate' 2 0+-- [0,0,0,...+--+-- >>> toVector $ replicate' 2 0+-- []+replicate' :: (Additive a, Eq a) => Natural -> a -> FiniteSupportStream a+replicate' n x =+  if x == zero+    then empty+    else MkFiniteSupportStream $ DV.replicate (fromIntegral n) x++-- | Adds an element to the front of the finite support stream.+-- The inner array size is increased by exactly one.+-- The head element of the array is not checked for zero elements.+--+-- ==== __Examples__+--+-- >>> cons 42 (unsafeFromList [1, 2, 3])+-- [42,1,2,3,0,0,0,...+--+-- >>> toVector $ cons 0 empty+-- [0]+cons :: a -> FiniteSupportStream a -> FiniteSupportStream a+cons x = MkFiniteSupportStream . DV.cons x . toVector++-- | Adds an element to the front of the finite support stream.+-- The inner array size is increased by exactly one if the head element is not zero.+-- Otherwise, if the finite support stream is empty, the output is also the empty stream.+--+-- ==== __Examples__+--+-- >>> cons' 42 (unsafeFromList [1, 2, 3])+-- [42,1,2,3,0,0,0,...+--+-- >>> toVector $ cons' 0 empty+-- []+cons' :: (Additive a, Eq a) => a -> FiniteSupportStream a -> FiniteSupportStream a+cons' x fss =+  let (MkFiniteSupportStream array') = optimize fss+   in if DV.null array'+        then singleton' x+        else MkFiniteSupportStream $ DV.cons x array'++-- | Creates a finite support stream basis vector.+-- The values of the zero and unit elements are provided as arguments.+--+-- ==== __Examples__+--+-- >>> finiteSupportStreamBasis 0 1 3+-- [0,0,0,1,0,0,0,...+finiteSupportStreamBasis :: a -> a -> Natural -> FiniteSupportStream a+finiteSupportStreamBasis zero' one' n =+  MkFiniteSupportStream $ DV.snoc (DV.replicate (fromIntegral n) zero') one'++-- | Convolves a stream with a finite support stream, producing a single value.+-- The result is the sum of element-wise products.+--+-- This operation is equivalent to applying the stream as a linear functional+-- to the finite support stream.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Float, Int)+-- >>> import GHC.Real ((/))+-- >>> import Data.Stream (iterate, take, Stream)+-- >>> import Data.HashMap.Internal.Array (fromList')+--+-- >>> s1 = iterate (+1) 0 :: Stream Int+-- >>> Data.Stream.take 5 s1+-- [0,1,2,3,4]+-- >>> fss1 = unsafeFromList [0, 0, 1] :: FiniteSupportStream Int+-- >>> streamsConvolution s1 fss1+-- 2+--+-- >>> s2 = iterate (/2) (1 :: Float) :: Stream Float+-- >>> Data.Stream.take 5 s2+-- [1.0,0.5,0.25,0.125,6.25e-2]+-- >>> fss2 = unsafeFromList $ Data.List.replicate 10 1 :: FiniteSupportStream Float+-- >>> streamsConvolution s2 fss2+-- 1.9980469+streamsConvolution ::+  (Distributive a) =>+  DS.Stream a ->+  FiniteSupportStream a ->+  a+streamsConvolution stream fss =+  foldl' (+) zero (DL.zipWith (*) (DS.toList stream) (toList fss))++-- | Applies the multiplicative action of the stream on the finite support stream.+-- The resulting stream's support length is less than or equal to+-- the stream's support length in the argument.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> multiplicativeAction (DS.fromList [0 ..]) (unsafeFromList [1, 1, 0, 1])+-- [0,1,0,3,0,0,0,...+multiplicativeAction ::+  (Multiplicative a) =>+  DS.Stream a ->+  FiniteSupportStream a ->+  FiniteSupportStream a+multiplicativeAction stream (MkFiniteSupportStream array) =+  MkFiniteSupportStream $+    DV.fromList $+      DL.zipWith (*) (DS.toList stream) (DV.toList array)++-- | Computes the sum of all elements the finite support stream.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> finiteSupportStreamSum $ unsafeFromList [1, 2, 3, 0] :: Int+-- 6+--+-- >>> finiteSupportStreamSum empty :: Int+-- 0+finiteSupportStreamSum :: (Additive a) => FiniteSupportStream a -> a+finiteSupportStreamSum (MkFiniteSupportStream array') = NumHask.sum array'++-- | Applies an element-wise binary operation to two streams.+--+-- Parameters:+--   * @f@ - Binary operation for overlapping elements+--   * @g@ - Unary operation for excess elements in first stream+--   * @h@ - Unary operation for excess elements in second stream+--+-- The resulting stream's length is the maximum of the input lengths,+-- with trailing elements transformed by @g@ or @h@ as appropriate.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> let xs = unsafeFromList [10, 20, 30]+-- >>> let ys = unsafeFromList [1,2]+-- >>> unsafeZipWith (-) id negate xs ys+-- [9,18,30,0,0,0,...+unsafeZipWith ::+  -- | Binary operation for overlapping elements+  (a -> b -> c) ->+  -- | Operation for excess elements in first stream+  (a -> c) ->+  -- | Operation for excess elements in second stream+  (b -> c) ->+  FiniteSupportStream a ->+  FiniteSupportStream b ->+  FiniteSupportStream c+unsafeZipWith f g h (MkFiniteSupportStream a0) (MkFiniteSupportStream a1) =+  MkFiniteSupportStream $ DVIBP.zipWith f g h a0 a1++-- | Lazy left fold over a foldable type @t@ and a `Data.Stream.Stream`.+--+-- ==== __Examples__+--+-- >>> foldlWithStream (\acc x y -> acc + x * y) 0 (unsafeFromList [1,1,1]) (DS.iterate (+1) 0)+-- 3+foldlWithStream ::+  (Foldable t) =>+  (b -> a -> c -> b) ->+  b ->+  t a ->+  DS.Stream c ->+  b+foldlWithStream f acc0 ta stream0 =+  fst $ foldl' step (acc0, stream0) ta+  where+    step (acc, DS.Cons c stream') a =+      (f acc a c, stream')++-- | Strinct left fold over a foldable type @t@ and a `Data.Stream.Stream`.+--+-- ==== __Examples__+--+-- >>> foldlWithStream (\acc x y -> acc + x * y) 0 (unsafeFromList [1,1,1]) (DS.iterate (+1) 0)+-- 3+foldlWithStream' ::+  (Foldable t) =>+  (b -> a -> c -> b) ->+  b ->+  t a ->+  DS.Stream c ->+  b+foldlWithStream' f !acc0 ta stream0 = fst $ foldl' step (acc0, stream0) ta+  where+    step (!acc, DS.Cons !c stream) a = let !acc' = f acc a c in (acc', stream)++-- | Zips two finite support streams.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+--+-- >>> unsafeZip (unsafeFromList [1, 2, 3]) (unsafeFromList [4, 5]) :: FiniteSupportStream (Int, Int)+-- [(1,4),(2,5),(3,0),(0,0),(0,0),(0,0),...+unsafeZip ::+  (Additive a, Additive b) =>+  FiniteSupportStream a ->+  FiniteSupportStream b ->+  FiniteSupportStream (a, b)+-- {-# ANN module "HLint: ignore Use zip" #-}+unsafeZip = unsafeZipWith (,) (,zero) (zero,)
+ src/Debug/DiffExpr.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-missing-export-lists #-}++-- | Module    :  Debug.SimpleExpr+-- Copyright   :  (C) 2023 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Tools for symbolic differentiation expressions.+module Debug.DiffExpr where++import Data.Fix (Fix (Fix))+import Debug.SimpleExpr.Expr+  ( SimpleExpr,+    SimpleExprF (SymbolicFuncF),+    unaryFunc,+  )+import Debug.SimpleExpr.Utils.Traced (Traced (MkTraced))+import Debug.Trace (trace)+import NumHask+  ( Additive,+    Distributive,+    Multiplicative,+    (*),+    (+),+  )+import Numeric.InfBackprop (RevDiff (MkRevDiff))+import Prelude (Show, String, show, ($), (<>))++-- | Create a binary function expression.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable)+--+-- >>> twoArgFunc "f" (variable "x") (variable "y")+-- f(x,y)+twoArgFunc :: String -> SimpleExpr -> SimpleExpr -> SimpleExpr+twoArgFunc name x y = Fix (SymbolicFuncF name [x, y])++-- | This typecalss is for creating symbolic unary function expressions.+--+-- It is used in conjunction with automatic differentiation to represent+-- functions symbolically.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable)+-- >>> import Numeric.InfBackprop (simpleDerivative)+--+-- >>> :{+--  f :: SymbolicFunc a => a -> a+--  f = unarySymbolicFunc "f"+-- :}+--+-- >>> f (variable "x")+-- f(x)+--+-- >>> simpleDerivative f (variable "x")+-- f'(x)*1+class SymbolicFunc a where+  unarySymbolicFunc :: String -> a -> a++-- | `SimpleExpr` instance of `SymbolicFunc` typeclass.+instance SymbolicFunc SimpleExpr where+  unarySymbolicFunc = unaryFunc++-- | `RevDiff` instance of `SymbolicFunc` typeclass.+instance+  (SymbolicFunc a, Multiplicative a) =>+  SymbolicFunc (RevDiff t a a)+  where+  unarySymbolicFunc :: String -> RevDiff t a a -> RevDiff t a a+  unarySymbolicFunc funcName (MkRevDiff x bp) =+    MkRevDiff+      (unarySymbolicFunc funcName x)+      (\cy -> bp $ f' * cy)+    where+      f' = unarySymbolicFunc (funcName <> "'") x++-- | This typecalss is for creating symbolic binary function expressions.+--+-- It is used in conjunction with automatic differentiation to represent+-- functions symbolically. See `SymbolicFunc` for unary functions.+class BinarySymbolicFunc a where+  binarySymbolicFunc :: String -> a -> a -> a++-- | `SimpleExpr` instance of `BinarySymbolicFunc` typeclass.+instance BinarySymbolicFunc SimpleExpr where+  binarySymbolicFunc = twoArgFunc++-- | `RevDiff` instance of `BinarySymbolicFunc` typeclass.+instance+  (BinarySymbolicFunc a, Distributive a, Additive t) =>+  BinarySymbolicFunc (RevDiff t a a)+  where+  binarySymbolicFunc funcName (MkRevDiff x bpx) (MkRevDiff y bpy) =+    MkRevDiff+      (binarySymbolicFunc funcName x y)+      (\cz -> bpx (f'1 * cz) + bpy (f'2 * cz))+    where+      f'1 = binarySymbolicFunc (funcName <> "'_1") x y+      f'2 = binarySymbolicFunc (funcName <> "'_2") x y++-- | A traced version of `SimpleExpr` for debugging purposes.+type TracedSimpleExpr = Traced SimpleExpr++-- | A type alias for `Traced` version of `SimpleExpr`.+type TSE = TracedSimpleExpr++-- | `Traced` instance of `SymbolicFunc` typeclass.+instance+  (SymbolicFunc a, Show a) =>+  SymbolicFunc (Traced a)+  where+  unarySymbolicFunc name (MkTraced x) =+    trace (" <<< TRACING: Calculating " <> name <> " of " <> show x <> " >>>") $+      MkTraced $+        unarySymbolicFunc name x++-- | `Traced` instance of `BinarySymbolicFunc` typeclass.+instance+  (BinarySymbolicFunc a, Show a) =>+  BinarySymbolicFunc (Traced a)+  where+  binarySymbolicFunc name (MkTraced x) (MkTraced y) =+    trace (" <<< TRACING: Calculating " <> name <> " of " <> show x <> " and " <> show y <> " >>>") $+      MkTraced $+        binarySymbolicFunc name x y
− src/Debug/LoggingBackprop.hs
@@ -1,368 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  Debug.LoggingBackprop--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Basics for simple expressions equipped with Monadic behaviour.--- In particular, basic functions with logging for debug and illustration purposes.--- See [this tutorial section](InfBackprop.Tutorial#differentiation_monadic_types) for details.-module Debug.LoggingBackprop-  ( -- * Generic logging functions-    unitConst,-    initUnaryFunc,-    initBinaryFunc,-    pureKleisli,-    backpropExpr,-    loggingBackpropExpr,--    -- * Logging functions examples-    const,-    linear,-    negate,-    (+),-    (*),-    pow,-    exp,-    sin,-    cos,-  )-where--import Control.Arrow (Kleisli (Kleisli))-import Control.CatBifunctor (first, second, (***))-import Control.Category ((.), (>>>))-import Control.Monad.Logger (MonadLogger, logInfoN)-import Data.Text (pack)-import Debug.SimpleExpr.Expr (SimpleExpr, unaryFunc)-import InfBackprop.Common (Backprop (MkBackprop), BackpropFunc)-import IsomorphismClass.Isomorphism (iso)-import NumHask (Additive, Distributive, Divisive, ExpField, Multiplicative, Subtractive, TrigField, fromInteger, zero)-import qualified NumHask as NH-import qualified NumHask.Prelude as NHP-import qualified Prelude.InfBackprop-import Prelude (Monad, Show, String, pure, return, show, ($), (<>))-import qualified Prelude as P---- | Logging constant function.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)------ >>> runStdoutLoggingT $ runKleisli (unitConst 42) ()--- [Info] Initializing 42--- 42-unitConst :: (Show a, MonadLogger m) => a -> Kleisli m () a-unitConst a = Kleisli $ \() -> do-  logInfoN $ "Initializing " <> pack (show a)-  pure a---- | Logging single argument function.------ ==== __Examples of usage__------ >>> import qualified Prelude as P--- >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)------ >>> plusTwo = initUnaryFunc "+2" (P.+2)--- >>> runStdoutLoggingT $ runKleisli plusTwo 3--- [Info] Calculating +2 of 3 => 5--- 5-initUnaryFunc :: (Show a, Show b, MonadLogger m) => String -> (a -> b) -> Kleisli m a b-initUnaryFunc msg f = Kleisli $ \a -> do-  let b = f a-  logInfoN $ "Calculating " <> pack msg <> " of " <> pack (show a) <> " => " <> pack (show b)-  pure b---- | Logging two argument (binary) function.------ ==== __Examples of usage__------ >>> import qualified Prelude as P--- >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)------ >>> loggingProduct = initBinaryFunc "product" (P.*)--- >>> runStdoutLoggingT $ runKleisli loggingProduct (6, 7)--- [Info] Calculating product of 6 and 7 => 42--- 42-initBinaryFunc :: (Show a, Show b, Show c, MonadLogger m) => String -> (a -> b -> c) -> Kleisli m (a, b) c-initBinaryFunc msg f = Kleisli $ \(a, b) -> do-  let c = f a b-  logInfoN $-    "Calculating "-      <> pack msg-      <> " of "-      <> pack (show a)-      <> " and "-      <> pack (show b)-      <> " => "-      <> pack (show c)-  return c---- | Returns pure Kleisli morphism given a map.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)------ >>> loggingDup = pureKleisli (\x -> (x, x))--- >>> runStdoutLoggingT $ runKleisli loggingDup 42--- (42,42)-pureKleisli :: Monad m => (a -> b) -> Kleisli m a b-pureKleisli f = Kleisli $ pure . f---- Differentiable functions.---- | Returns symbolically differentiable Simple Expression.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)--- >>> import Debug.SimpleExpr.Expr (variable)--- >>> import InfBackprop (call, derivative, backpropExpr)------ >>> x = variable "x"--- >>> f = backpropExpr "f"--- >>> call f x--- f(x)------ >>> derivative f x--- 1·f'(x)-backpropExpr :: String -> BackpropFunc SimpleExpr SimpleExpr-backpropExpr funcName = MkBackprop call_ forward_ backward_-  where-    call_ = unaryFunc funcName-    forward_ = Prelude.InfBackprop.dup >>> first (backpropExpr funcName :: BackpropFunc SimpleExpr SimpleExpr)-    backward_ = second (backpropExpr (funcName <> "'")) >>> (Prelude.InfBackprop.*)---- | Returns symbolically differentiable logging symbolic function.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)--- >>> import Debug.SimpleExpr.Expr (variable)--- >>> import InfBackprop (call, derivative)------ >>> x = variable "x"--- >>> f = loggingBackpropExpr "f"--- >>> runStdoutLoggingT $ runKleisli (call f) x--- [Info] Calculating f of x => f(x)--- f(x)------ >>> runStdoutLoggingT $ runKleisli (derivative f) x--- [Info] Calculating f of x => f(x)--- [Info] Calculating f' of x => f'(x)--- [Info] Calculating multiplication of 1 and f'(x) => 1·f'(x)--- 1·f'(x)-loggingBackpropExpr :: forall m. (MonadLogger m) => String -> Backprop (Kleisli m) SimpleExpr SimpleExpr-loggingBackpropExpr funcName = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m SimpleExpr SimpleExpr-    call' = initUnaryFunc funcName (unaryFunc funcName)--    forward' :: Backprop (Kleisli m) SimpleExpr (SimpleExpr, SimpleExpr)-    forward' = dup >>> first (loggingBackpropExpr funcName :: Backprop (Kleisli m) SimpleExpr SimpleExpr)--    backward' :: Backprop (Kleisli m) (SimpleExpr, SimpleExpr) SimpleExpr-    backward' = second (loggingBackpropExpr (funcName <> "'")) >>> (*)---- | Differentiable logging constant function.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)--- >>> import Debug.SimpleExpr.Expr (variable)--- >>> import InfBackprop (call, derivative)------ >>> runStdoutLoggingT $ runKleisli (call (const 42)) ()--- 42-const ::-  forall c x m.-  (Additive c, Additive x, Show c, Show x, Monad m) =>-  c ->-  Backprop (Kleisli m) x c-const c = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x c-    call' = Kleisli $ P.const (pure c)--    forward' :: Backprop (Kleisli m) x (c, ())-    forward' = const c >>> (iso :: Backprop (Kleisli m) c (c, ()))--    backward' :: Backprop (Kleisli m) (c, ()) x-    backward' = const zero---- | Differentiable dup logging function.-dup :: forall x m. (Show x, Additive x, MonadLogger m) => Backprop (Kleisli m) x (x, x)-dup = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x (x, x)-    call' = pureKleisli (\x -> (x, x))--    forward' :: Backprop (Kleisli m) x ((x, x), ())-    forward' = dup >>> (iso :: Backprop (Kleisli m) y (y, ()))--    backward' :: Backprop (Kleisli m) ((x, x), ()) x-    backward' = (iso :: Backprop (Kleisli m) (y, ()) y) >>> (+)---- | Differentiable logging sum function.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)--- >>> import InfBackprop (call)------ >>> runStdoutLoggingT $ runKleisli (call (+)) (2, 2)--- [Info] Calculating sum of 2 and 2 => 4--- 4-(+) :: forall x m. (Show x, Additive x, MonadLogger m) => Backprop (Kleisli m) (x, x) x-(+) = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m (x, x) x-    call' = initBinaryFunc "sum" (NH.+)--    forward' :: Backprop (Kleisli m) (x, x) (x, ())-    forward' = (+) >>> (iso :: Backprop (Kleisli m) y (y, ()))--    backward' :: Backprop (Kleisli m) (x, ()) (x, x)-    backward' = (iso :: Backprop (Kleisli m) (x, ()) x) >>> dup---- | Differentiable logging multiplication function.------ ==== __Examples of usage__------ >>> import Control.Arrow (runKleisli)--- >>> import Control.Monad.Logger (runStdoutLoggingT)--- >>> import InfBackprop (call)------ >>> runStdoutLoggingT $ runKleisli (call (*)) (6, 7)--- [Info] Calculating multiplication of 6 and 7 => 42--- 42-(*) ::-  forall x m.-  (Show x, Additive x, Multiplicative x, MonadLogger m) =>-  Backprop (Kleisli m) (x, x) x-(*) = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m (x, x) x-    call' = initBinaryFunc "multiplication" (NH.*)--    forward' :: Backprop (Kleisli m) (x, x) (x, (x, x))-    forward' = dup >>> first (*)--    backward' :: Backprop (Kleisli m) (x, (x, x)) (x, x)-    backward' =-      first dup-        >>> (iso :: Backprop (Kleisli m) ((dy, dy), (x1, x2)) ((dy, x1), (dy, x2)))-        >>> (iso :: Backprop (Kleisli m) (a, b) (b, a))-        >>> ((*) *** (*))---- | Differentiable logging linear function.-linear ::-  forall x m.-  (Show x, NH.Distributive x, MonadLogger m) =>-  x ->-  Backprop (Kleisli m) x x-linear c = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc ("linear " <> show c) (c NH.*)--    forward' :: Backprop (Kleisli m) x (x, ())-    forward' = linear c >>> (iso :: Backprop (Kleisli m) y (y, ()))--    backward' :: Backprop (Kleisli m) (x, ()) x-    backward' = (iso :: Backprop (Kleisli m) (x, ()) x) >>> linear c---- | Differentiable logging negate function.-negate ::-  forall x m.-  (Show x, Subtractive x, MonadLogger m) =>-  Backprop (Kleisli m) x x-negate = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc "negate" NH.negate--    forward' :: Backprop (Kleisli m) x (x, ())-    forward' = negate >>> (iso :: Backprop (Kleisli m) y (y, ()))--    backward' :: Backprop (Kleisli m) (x, ()) x-    backward' = (iso :: Backprop (Kleisli m) (y, ()) y) >>> negate---- | Differentiable logging exponent function.-exp ::-  forall x m.-  (ExpField x, Show x, MonadLogger m) =>-  Backprop (Kleisli m) x x-exp = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc "exp" NH.exp--    forward' :: Backprop (Kleisli m) x (x, x)-    forward' = (exp :: Backprop (Kleisli m) x x) >>> dup--    backward' :: Backprop (Kleisli m) (x, x) x-    backward' = (*)---- | Differentiable logging power function.-pow ::-  forall x m.-  (Show x, Divisive x, Distributive x, Subtractive x, NH.FromIntegral x NHP.Integer, MonadLogger m) =>-  NHP.Integer ->-  Backprop (Kleisli m) x x-pow n = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc ("pow " <> show n) (NH.^ fromInteger n)--    forward' :: Backprop (Kleisli m) x (x, x)-    forward' = dup >>> first (pow n :: Backprop (Kleisli m) x x)--    backward' :: Backprop (Kleisli m) (x, x) x-    backward' = second (pow (n P.- 1) >>> linear (NH.fromIntegral n)) >>> (*)---- | Differentiable logging sin function.-sin ::-  forall x m.-  (Show x, TrigField x, MonadLogger m) =>-  Backprop (Kleisli m) x x-sin = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc "sin" NH.sin--    forward' :: Backprop (Kleisli m) x (x, x)-    forward' = dup >>> first (sin :: Backprop (Kleisli m) x x)--    backward' :: Backprop (Kleisli m) (x, x) x-    backward' = second (cos :: Backprop (Kleisli m) x x) >>> (*)---- | Differentiable logging cos function.-cos ::-  forall x m.-  (Show x, TrigField x, MonadLogger m) =>-  Backprop (Kleisli m) x x-cos = MkBackprop call' forward' backward'-  where-    call' :: Kleisli m x x-    call' = initUnaryFunc "cos" NH.cos--    forward' :: Backprop (Kleisli m) x (x, x)-    forward' = dup >>> first (sin :: Backprop (Kleisli m) x x)--    backward' :: Backprop (Kleisli m) (x, x) x-    backward' = second (sin >>> negate :: Backprop (Kleisli m) x x) >>> (*)
− src/InfBackprop.hs
@@ -1,125 +0,0 @@-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  InfBackprop--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Automatic differentiation and backpropagation.--- See 'InfBackprop.Tutorial' for details.-module InfBackprop-  ( -- * Base--    -- ** Types-    Backprop (MkBackprop),-    BackpropFunc,-    -- Manipulations-    call,-    forward,-    backward,-    derivative,-    derivativeN,--    -- ** Categorical Bifunctor-    (***),-    first,-    second,--    -- * Differentiable functions--    -- ** Elementary functions-    const,-    linear,-    (+),-    (-),-    negate,-    (*),-    (/),--    -- ** Tuple manipulations-    dup,-    setFirst,-    setSecond,-    forget,-    forgetFirst,-    forgetSecond,--    -- ** Exponential family functions-    log,-    logBase,-    exp,-    (**),-    pow,--    -- ** Trigonometric functions-    cos,-    sin,-    tan,-    asin,-    acos,-    atan,-    atan2,-    sinh,-    cosh,-    tanh,-    asinh,-    acosh,-    atanh,--    -- * Monadic differentiable functions-    pureBackprop,-    backpropExpr,-    loggingBackpropExpr,--    -- * Tools-    pureKleisli,-    simpleDifferentiable,-  )-where--import Control.CatBifunctor (first, second, (***))-import Debug.LoggingBackprop (backpropExpr, loggingBackpropExpr, pureKleisli)-import InfBackprop.Common-  ( Backprop (MkBackprop),-    BackpropFunc,-    backward,-    call,-    const,-    derivative,-    derivativeN,-    forward,-    pureBackprop,-  )-import Prelude.InfBackprop-  ( acos,-    acosh,-    asin,-    asinh,-    atan,-    atan2,-    atanh,-    cos,-    cosh,-    dup,-    exp,-    forget,-    forgetFirst,-    forgetSecond,-    linear,-    log,-    logBase,-    negate,-    pow,-    setFirst,-    setSecond,-    simpleDifferentiable,-    sin,-    sinh,-    tan,-    tanh,-    (*),-    (**),-    (+),-    (-),-    (/),-  )
− src/InfBackprop/Common.hs
@@ -1,340 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  InfBackprop.Common--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Provides base types and methods for backpropagation category morphism.-module InfBackprop.Common-  ( -- * Basic-    Backprop (MkBackprop),-    call,-    forward,-    backward,-    StartBackprop,-    startBackprop,-    forwardBackward,-    numba,-    numbaN,-    derivative,-    derivativeN,--    -- * Differentiable functions-    BackpropFunc,-    const,--    -- * Differentiable monadic functions-    pureBackprop,-  )-where--import Control.Arrow (Kleisli (Kleisli))-import Control.CatBifunctor (CatBiFunctor, first, (***))-import Control.Category (Category, id, (.), (>>>))-import GHC.Natural (Natural)-import IsomorphismClass (IsomorphicTo)-import IsomorphismClass.Extra ()-import IsomorphismClass.Isomorphism (Isomorphism, iso)-import NumHask (one, zero)-import NumHask.Algebra.Additive (Additive)-import NumHask.Algebra.Ring (Distributive)-import NumHask.Extra ()-import Prelude (Monad, flip, fromIntegral, iterate, pure, (!!), ($))-import qualified Prelude as P---- | Backprop morphism.--- #backprop#--- Base type for an infinitely differentiable object.--- It depends on categorical type @cat@ that is mostly common @(->)@,--- see 'BackpropFunc' which by it's definition is equivalent to------ @--- data BackpropFunc input output = forall cache. MkBackpropFunc {---  call     :: input -> output,---  forward  :: BackpropFunc input (output, cache),---  backward :: BackpropFunc (output, cache) input--- }--- @------ The diagram below illustrates the how it works for the first derivative.--- Consider the role of function @f@ in the derivative of the composition @g(f(h(...)))@.--- #backprop_func#------ @---   h        ·                  f                   ·        g---            ·                                      ·---            ·               forward                ·---            · --- input  >-----+-----> output >--- ·---            ·                  V                   ·---  ...       ·                  |                   ·       ...---            ·                  | cache             ·---            ·                  |                   ·---            ·                  V                   ·---            · --< dInput <-----+-----< dOutput <-- ·---            ·               backward               ·--- @------ Notice that 'forward' and 'backward' are of type 'BackpropFunc' but not @(->)@.--- This is needed for further differentiation.--- However for the first derivative this difference can be ignored.------ The return type of 'forward' contains additional term @cache@.--- It is needed to save and transfer data calculated in the forward step to the backward step for reuse.--- See an example in------ [Differentiation with logging](#differentiation_with_logging)--- section .------ == __Remark__--- Mathematically speaking we have to distinguish the types for 'forward' and for 'backward' methods because the second--- acts on the cotangent bundle.--- However, for simplicity and due to technical reasons we identify the types @input@ and @dInput@--- as well as @output@ and @dOutput@ which is enough for our purposes because these types are usually real numbers--- or arrays of real numbers.-data Backprop cat input output = forall cache.-  MkBackprop-  { -- | Simple internal category object extraction.-    call :: cat input output,-    -- | Returns forward category.-    -- In the case @cat = (->)@, the method coincides with 'Backprop'@ cat input output@ itself-    -- but the output contains an additional data term @cache@ with some calculation result that can be reused on in-    -- 'backward'.-    forward :: Backprop cat input (output, cache),-    -- | Returns backward category. In the case @cat = (->)@, the method takes the additional data term @cache@ that is-    -- calculated in 'forward'.-    backward :: Backprop cat (output, cache) input-  }--composition' ::-  forall cat x y z.-  (Isomorphism cat, CatBiFunctor (,) cat) =>-  Backprop cat x y ->-  Backprop cat y z ->-  Backprop cat x z-composition'-  (MkBackprop callF (forwardF :: Backprop cat x (y, hF)) (backwardF :: Backprop cat (y, hF) x))-  (MkBackprop callG (forwardG :: Backprop cat y (z, hG)) (backwardG :: Backprop cat (z, hG) y)) =-    MkBackprop call_ forward_ backward_-    where-      call_ :: cat x z-      call_ = callF >>> callG--      forward_ :: Backprop cat x (z, (hG, hF))-      forward_ =-        (forwardF `composition'` first forwardG) `composition'` (iso :: Backprop cat ((z, hG), hF) (z, (hG, hF)))--      backward_ :: Backprop cat (z, (hG, hF)) x-      backward_ =-        (iso :: Backprop cat (z, (hG, hF)) ((z, hG), hF)) `composition'` first backwardG `composition'` backwardF--iso' ::-  forall cat x y.-  (IsomorphicTo x y, Isomorphism cat, CatBiFunctor (,) cat) =>-  Backprop cat x y-iso' = MkBackprop call_ (forward_ :: Backprop cat x (y, ())) (backward_ :: Backprop cat (y, ()) x)-  where-    call_ :: cat x y-    call_ = iso--    forward_ :: Backprop cat x (y, ())-    forward_ = (iso :: Backprop cat x y) `composition'` (iso :: Backprop cat y (y, ()))--    backward_ :: Backprop cat (y, ()) x-    backward_ = (iso :: Backprop cat (y, ()) y) `composition'` (iso :: Backprop cat y x)--instance-  (Isomorphism cat, CatBiFunctor (,) cat) =>-  Category (Backprop cat)-  where-  id = iso'-  (.) = flip composition'--instance-  (Isomorphism cat, CatBiFunctor (,) cat) =>-  Isomorphism (Backprop cat)-  where-  iso = iso'--instance-  (Isomorphism cat, CatBiFunctor (,) cat) =>-  CatBiFunctor (,) (Backprop cat)-  where-  (***)-    (MkBackprop call1 (forward1 :: Backprop cat x1 (y1, h1)) (backward1 :: Backprop cat (y1, h1) x1))-    (MkBackprop call2 (forward2 :: Backprop cat x2 (y2, h2)) (backward2 :: Backprop cat (y2, h2) x2)) =-      MkBackprop call12 forward12 backward12-      where-        call12 :: cat (x1, x2) (y1, y2)-        call12 = call1 *** call2--        forward12 :: Backprop cat (x1, x2) ((y1, y2), (h1, h2))-        forward12 = forward1 *** forward2 >>> (iso :: Backprop cat ((y1, h1), (y2, h2)) ((y1, y2), (h1, h2)))--        backward12 :: Backprop cat ((y1, y2), (h1, h2)) (x1, x2)-        backward12 = (iso :: Backprop cat ((y1, y2), (h1, h2)) ((y1, h1), (y2, h2))) >>> backward1 *** backward2---- | Implementation of the process illustrated in the--- [diagram](#backprop_func).--- The first argument is a backprop morphism @y -> dy@--- The second argument is a backprop morphism @x -> y@--- The output is the backprop @x -> dx@ build according the--- [diagram](#backprop_func)-forwardBackward ::-  (Isomorphism cat, CatBiFunctor (,) cat) =>-  -- | backprop morphism between @y@ and @dy@-  -- that is inferred after the forward step for @f@ and before the backward step for @f@-  Backprop cat y y ->-  -- | some backprop morphism @f@ between @x@ and @y@-  Backprop cat x y ->-  -- | the output backprop morphism from @x@ to @dx@ that is the composition.-  Backprop cat x x-forwardBackward dy (MkBackprop _ forward_ backward_) = forward_ >>> first dy >>> backward_---- | Interface for categories @cat@ and value types @x@ that support starting the backpropagation.--- For example for @(->)@ and @Float@ we are able to start the backpropagation like--- @f(g(x))@ -> @1 · f'(g(x)) · ...@--- because @f@ is a @Float@ valued (scalar) function.--- Calculating Jacobians is not currently implemented.-class Distributive x => StartBackprop cat x where-  -- | Morphism that connects forward and backward chain.-  -- Usually it is just @1@ that is supposed to be multiplied on the derivative of the top function.-  startBackprop :: Backprop cat x x---- | Backpropagation derivative in terms of backprop morphisms.-numba ::-  (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat y) =>-  Backprop cat x y ->-  Backprop cat x x-numba = forwardBackward startBackprop---- | Backpropagation ns derivative in terms of backprop morphisms.-numbaN ::-  (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat x) =>-  Natural ->-  Backprop cat x x ->-  Backprop cat x x-numbaN n f = iterate numba f !! fromIntegral n---- | Backpropagation derivative as categorical object.--- If @cat@ is @(->)@ the output is simply a function.------ ==== __Examples of usage__------ >>> import InfBackprop (sin)--- >>> import Prelude (Float)--- >>> derivative sin (0 :: Float)--- 1.0-derivative ::-  (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat y) =>-  Backprop cat x y ->-  cat x x-derivative = call . numba---- | Backpropagation derivative of order n as categorical object.--- If @cat@ is @(->)@ the output is simply a function.------ ==== __Examples of usage__------ >>> import InfBackprop (pow, const)--- >>> import Prelude (Float, fmap)--- >>> myFunc = (pow 2) :: Backprop (->) Float Float------ >>> fmap (derivativeN 0 myFunc) [-3, -2, -1, 0, 1, 2, 3]--- [9.0,4.0,1.0,0.0,1.0,4.0,9.0]------ >>> fmap (derivativeN 1 myFunc) [-3, -2, -1, 0, 1, 2, 3]--- [-6.0,-4.0,-2.0,0.0,2.0,4.0,6.0]------ >>> fmap (derivativeN 2 myFunc) [-3, -2, -1, 0, 1, 2, 3]--- [2.0,2.0,2.0,2.0,2.0,2.0,2.0]------ >>> fmap (derivativeN 3 myFunc) [-3, -2, -1, 0, 1, 2, 3]--- [0.0,0.0,0.0,0.0,0.0,0.0,0.0]-derivativeN ::-  (Isomorphism cat, CatBiFunctor (,) cat, StartBackprop cat x) =>-  Natural ->-  Backprop cat x x ->-  cat x x-derivativeN n = call . numbaN n---- | Infinitely differentiable function.--- The definition of the type synonym is equivalent to------ @--- data BackpropFunc input output = forall cache. MkBackpropFunc {---    call     :: input -> output,---    forward  :: BackpropFunc input (output, cache),---    backward :: BackpropFunc (output, cache) input---  }--- @------ See 'Backprop' for details.------ ==== __Examples of usage__------ >>> import Prelude (fmap, Float)--- >>> import InfBackprop (pow, call, derivative)--- >>> myFunc = pow 2 :: BackpropFunc Float Float--- >>> f = call myFunc :: Float -> Float--- >>> fmap f [-3, -2, -1, 0, 1, 2, 3]--- [9.0,4.0,1.0,0.0,1.0,4.0,9.0]--- >>> df = derivative myFunc :: Float -> Float--- >>> fmap df [-3, -2, -1, 0, 1, 2, 3]--- [-6.0,-4.0,-2.0,0.0,2.0,4.0,6.0]-type BackpropFunc = Backprop (->)--instance forall x. (Distributive x) => StartBackprop (->) x where-  startBackprop = const one---- | Infinitely differentiable constant function.------ === __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative, derivativeN)------ >>> call (const 5) ()--- 5------ >>> derivative (const (5 :: Float)) 42--- 0------ >>> derivativeN 2 (const (5 :: Float)) 42--- 0.0-const ::-  forall c x.-  (Additive c, Additive x) =>-  c ->-  BackpropFunc x c-const c = MkBackprop call' forward' backward'-  where-    call' :: x -> c-    call' = P.const c-    forward' :: BackpropFunc x (c, ())-    forward' = const c >>> (iso :: BackpropFunc c (c, ()))-    backward' :: BackpropFunc (c, ()) x-    backward' = (iso :: BackpropFunc (c, ()) c) >>> const zero---- | Lifts a backprop function morphism to the corresponding pure Kleisli morphism.-pureBackprop :: forall a b m. Monad m => Backprop (->) a b -> Backprop (Kleisli m) a b-pureBackprop-  ( MkBackprop-      (call'' :: a -> b)-      (forward'' :: Backprop (->) a (b, c))-      (backward'' :: Backprop (->) (b, c) a)-    ) =-    MkBackprop call' forward' backward'-    where-      call' :: Kleisli m a b-      call' = Kleisli $ pure . call''--      forward' :: Backprop (Kleisli m) a (b, c)-      forward' = pureBackprop forward''--      backward' :: Backprop (Kleisli m) (b, c) a-      backward' = pureBackprop backward''--instance (Distributive x, Monad m) => StartBackprop (Kleisli m) x where-  startBackprop = pureBackprop startBackprop
− src/InfBackprop/Tutorial.hs
@@ -1,474 +0,0 @@-{-# OPTIONS_GHC -fno-warn-unused-imports #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  InfBackprop.Tutorial--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Tutorial [inf-backprop](https://hackage.haskell.org/package/inf-backprop) package.-module InfBackprop.Tutorial-  ( -- * Quick start-    -- $quick_start--    -- * Derivatives for symbolic expressions-    -- $derivatives_for_symbolic_expressions--    -- * Symbolic expressions visualization-    -- $symbolic_expressions_visualization--    -- * How it works-    -- $how_it_works--    -- * Declaring custom derivative-    -- $declaring_custom_derivative--    -- * Differentiation of monadic function-    -- $differentiation_monadic_types--    -- * Differentiation with logging-    -- $differentiation_with_logging-  )-where--import Control.Arrow (Kleisli, (<<<), (>>>))-import Control.Monad.Logger (MonadLogger)-import Debug.SimpleExpr (SimpleExpr, simplify)-import InfBackprop-  ( Backprop,-    BackpropFunc,-    backward,-    call,-    cos,-    derivative,-    first,-    forward,-    pow,-    pureBackprop,-    second,-    (***),-  )-import Prelude (Maybe (Just, Nothing), Monad)---- $quick_start--- >>> :set -XNoImplicitPrelude--- >>> import Prelude (Float, fmap)--- >>> import InfBackprop (BackpropFunc, call, derivative, derivativeN, pow)------ We can define differentiable function------ \[---   f(x) := x^2--- \]------ as follows------ >>> smoothF = pow 2 :: BackpropFunc Float Float------ where 'pow' is a power differentiable function and--- 'BackpropFunc'@ :: * -> * -> * @--- is a type for infinitely differentiable (smooth) functions.--- We can get the function values by 'call' method like------ >>> f = call smoothF :: Float -> Float--- >>> fmap f [-3, -2, -1, 0, 1, 2, 3]--- [9.0,4.0,1.0,0.0,1.0,4.0,9.0]------ as well as the first derivative by 'derivative', which is------ \[---   f'(x) = 2 \cdot x--- \]------ >>> df = derivative smoothF :: Float -> Float--- >>> fmap df [-3, -2, -1, 0, 1, 2, 3]--- [-6.0,-4.0,-2.0,0.0,2.0,4.0,6.0]------ or the second derivative------ \[---   f''(x) = 2--- \]------ >>> d2f = derivativeN 2 smoothF :: Float -> Float--- >>> fmap d2f [-3, -2, -1, 0, 1, 2, 3]--- [2.0,2.0,2.0,2.0,2.0,2.0,2.0]------ and so on.------ A composition of two functions like------ \[---   g(x) := \log x^3--- \]------ must be defined with the categorical composition '(>>>)' (or '(<<<)')------ >>> import InfBackprop (log)--- >>> import Control.Category ((>>>), (<<<))--- >>> smoothG = pow 3 >>> log------ For more complicated expressions, for example,------ \[---   h(x) := x^2 + x^3--- \]------ we use arrow notations '(***)', 'first' and 'second' as follows------ >>> import InfBackprop ((+), dup)--- >>> import Control.CatBifunctor ((***))------ >>> smoothH = dup >>> (pow 2 *** pow 3) >>> (+) :: BackpropFunc Float Float------ where------ @---   dup :: BackpropFunc a (a, a)--- @------ is differentiable function that simply splits the single implicit argument @x@ into the tuple '(x, x)'.--- THis is needed path tje implicit @x@ to two independent functions 'pow' @2@ and 'pow' @3@.--- The last------ @---   (+) :: BackpropFunc (a, a) a--- @------ operation transforms the pair of implicit arguments into their sum.---- $derivatives_for_symbolic_expressions------ >>> import Prelude (($))--- >>> import Control.Category ((<<<))--- >>> import InfBackprop (BackpropFunc, call, derivative, derivativeN, sin, pow, (**), pow, setSecond, const)------ We use--- [simple-expr](https://hackage.haskell.org/package/simple-expr)--- package here.------ >>> import Debug.SimpleExpr.Expr (SimpleExpr, variable, simplify)------ For example a symbolic function------ \[---   f(x) := \sin x^2--- \]------ can be defined as follows------ >>> x = variable "x"--- >>> f = sin <<< pow 2 :: BackpropFunc SimpleExpr SimpleExpr------ see 'Debug.SimpleExpr.Tutorial' for details.--- We can call the symbolic function like------ >>> call f x--- sin(x·x)------ and find the symbolic derivative------ \[---   \frac{d}{d x} f(x) = \frac{d}{d x} \sin x^2 = 2\, x \cos x^2--- \]------ as follows------ >>> simplify $ derivative f x--- cos(x·x)·(2·x)------ as well as the second and higher derivatives------ >>> simplify $ derivativeN 2 f x--- (((2·x)·-(sin(x·x)))·(2·x))+(2·cos(x·x))---- $symbolic_expressions_visualization--- The--- [simple-expr](https://hackage.haskell.org/package/simple-expr)--- package is equipped with a visulaisation tool that can be used to illustrate how the differentiation works.------ >>> import Control.Category ((<<<))--- >>> import InfBackprop (call, backpropExpr)--- >>> import Debug.SimpleExpr.Expr (SimpleExpr, variable, simplify)--- >>> import Debug.SimpleExpr.GraphUtils (exprToGraph)--- >>> import Data.Graph.VisualizeAlternative (plotDGraph)------ As a warm up consider a trivial composition of two functions------ \[---   g(f(x))--- \]------ is defined as------ >>> x = variable "x"--- >>> call (backpropExpr "g" <<< backpropExpr "f") x--- g(f(x))------ It can be plotted by------ @ plotExpr $ call (backpropExpr "g" <<< backpropExpr "f") x @------ ![image description](doc/images/composition.png)------ The graph for the first derivative can depicted by------ @ plotExpr $ simplify $ derivative (backpropExpr "g" <<< backpropExpr "f") x @------ ![image description](doc/images/composition_derivative.png)------ where--- 'simplify'@ :: @'SimpleExpr'@ -> @'SimpleExpr`--- is a simple removal such things like @*1@ and @+0@.------ As well as the second derivative is straightforward------ @ plotExpr $ simplify $ derivativeN 2 (backpropExpr "g" <<< backpropExpr "f") x @------ ![image description](doc/images/composition_second_derivative.png)---- $how_it_works--- The idea would be clear from the example of three functions composition------ \[---   g(f(h(x)))--- \]--- with a focus on function @f@.------ Its first derivative over @x@ is------ \[---   g(f(h(x))).--- \]------ \[---   h'(x) \cdot f'(h(x)) \cdot g'(f(h(x))).--- \]------ According to the backpropagation strategy, the order of the calculation should be as follows.------ 1. Find @h(x)@.------ 2. Find @f(h(x))@.------ 3. Find @g(f(h(x)))@.------ 4. Find the top derivative @g'(f(h(x)))@.------ 5. Find the next to the top derivative @f'(h(x))@.------ 6. Multiply @g'(f(h(x)))@ on @f'(h(x))@.------ 7. Find the next derivative @h'(x)@.------ 8. Multiply the output of point 6 on @h'(x)@.------ The generalization for longer composition is straightforward.------ All calculations related to the function @f@ can be divided into two parts.--- We have to find @f@ of @h(x)@ first (forward step) and then the derivative @f'@ of the same argument @h(x)@ and--- multiply it on the derivative @g'(f(h(x)))@ obtained during the similar calculations for @g@ (backward step).--- Notice that the value of @h(x)@ is reused on the backward step.--- To implement this, we define type 'Backprop' (see the corresponding--- documentation for details).---- $declaring_custom_derivative--- >>> import Prelude (Float)--- >>> import qualified Prelude--- >>> import Control.Category ((>>>))--- >>> import InfBackprop ((*), negate, dup, BackpropFunc, Backprop(MkBackprop), second)------ As an illustrative example a differentiable version of 'cos' numerical function can be defined as follows--- (see the documentation for 'Backprop' for details)------ @---   cos :: BackpropFunc Float Float---   cos = MkBackprop call' forward' backward' where---     call' :: Float -> Float---     call' = Prelude.cos------     forward' :: BackpropFunc Float (Float, Float)---     forward' = dup >>> first cos------     backward' :: BackpropFunc (Float, Float) Float---     backward' = second (sin >>> negate) >>> (*)------   sin :: BackpropFunc Float Float---   sin = ...--- @------ Here we use @Prelude@ implementation for ordinary @cos@ function in 'call'.--- The forward function is differentiable (which is needed for further derivatives) function--- with two output values.--- Roughly speaking 'forward' is--- @x -> (sin x, x)@.--- The first term of the tuple is just @sin@ and--- the second terms @x@ in the tuple is the value to be reused on the backward step.--- The 'backward' is--- @(dy, x) -> dy * (-cos x)@,--- where @dy@ is the derivative found on the previous backward step and the second value is @x@ stored by `forward`.--- We simply multiply with @(*)@ the derivative @dy@ on the derivative of @sin@ that is @-cos@.------ The stored value is not necessary just @x@. It could be anything useful for the backward step, see for example--- the implementation for @exp@ and the corresponding--- [example](InfBackprop.Tutorial#differentiation_with_logging)--- below.---- $differentiation_monadic_types #differentiation_monadic_types#--- Differentiable versions of monadic functions @a -> m b@ can also be backpropagated.--- For example, consider a real-valued power function defined for positive real numbers.--- For a negative number, it returns 'Nothing', which is a signal to stop computing the derivative and return 'Nothing'--- in the spirit of the behavior of the monad 'Maybe'.--- For this purpose, we can use that the type 'Backprop' type is defined for any category,--- not only for functions @(->)@.--- In particular, we can try 'Backprop'@(@'Kleisli' 'Maybe'@)@ instead of 'Backprop'@(->)@ from the previous sections.------ >>> import Prelude (Maybe, Maybe(Just, Nothing), ($), Ord, (>), Float)--- >>> import InfBackprop (Backprop(MkBackprop), derivative, dup, (*), linear, pureBackprop, first, second)--- >>> import Control.Arrow (Kleisli(Kleisli), runKleisli, (>>>))--- >>> import qualified NumHask as NH------ The functoin------ @---  pureBackprop :: Monad m => Backprop (->) a b -> Backprop (Kleisli m) a b--- @------ is to trivially lift an ordinary backpropagation functions to the monadic function type.------ Define the power function as follows------ >>> :{---  powR :: forall a. (Ord a, NH.ExpField a) =>---    a -> Backprop (Kleisli Maybe) a a---  powR p = MkBackprop call' forward' backward'---    where---      call' :: Kleisli Maybe a a---      call' = Kleisli $ \x -> if x > NH.zero---        then Just $ x NH.** p---        else Nothing---      -----      forward' :: Backprop (Kleisli Maybe) a (a, a)---      forward' = pureBackprop dup >>> first (powR p)---      -----      backward' :: Backprop (Kleisli Maybe) (a, a) a---      backward' = second der >>> pureBackprop (*) where---        der = powR (p NH.- NH.one) >>> pureBackprop (linear p)--- :}------ and calculate------ \[---  \frac{d}{dx} x^{\frac12} = \frac{1}{2 \sqrt{x}}--- \]------ for @x=4@ and @x=-4@ like------ >>> runKleisli (derivative (powR 0.5)) (4 :: Float)--- Just 0.25--- >>> runKleisli (derivative (powR 0.5)) (-4 :: Float)--- Nothing---- $differentiation_with_logging #differentiation_with_logging#------ Our objective now is to add logging to the derivative calculation.--- The type 'Backprop' @cat a b@ type is parametrized by a category @cat@, input @a@ and output @b@.--- If @cat@ is @(->)@ the type is reduced to 'BackpropFunc' we worked with above.--- To add logging to the calculation we shall replace @(->)@ by--- 'MonadLogger' @m =>@ 'Kleisli' @m@.--- We will need the imports below------ >>> import Prelude (Integer, Float, ($), (+), (*))--- >>> import Control.Monad.Logger (runStdoutLoggingT, MonadLogger)--- >>> import Control.Arrow ((>>>), runKleisli, Kleisli)--- >>> import InfBackprop (derivative, loggingBackpropExpr)--- >>> import Debug.SimpleExpr.Expr (variable)--- >>> import Debug.LoggingBackprop (initUnaryFunc, initBinaryFunc, pureKleisli, exp, sin)------ where the module 'Debug.loggingBackpropExpr' contains some useful functionality.--- For example, lifts for unary functions------ @---  initUnaryFunc :: (Show a, Show b, MonadLogger m) => String -> (a -> b) -> Kleisli m a b--- @------ and binary functions------ @---  initBinaryFunc :: (Show a, Show b, Show c, MonadLogger m) => String -> (a -> b -> c) -> Kleisli m (a, b) c--- @------ These two terms map given functions to Kleisli category terms, that allows logging during their execution.------ Let us first explain how it works with the following example.------ \[---  f(x) = y \cdot 3 + y \cdot 4, \quad y = x + 2.--- \]------ This function can be defined as follows------ >>> :{---  fLogging :: MonadLogger m => Kleisli m Integer Integer---  fLogging =---    initUnaryFunc "+2" (+2) >>>---    (pureKleisli (\x -> (x, x))) >>>---    (initUnaryFunc "*3" (*3) *** initUnaryFunc "*4" (*4)) >>>---    initBinaryFunc "sum" (+)--- :}------ We run the calculation with @ x = 5 @ as follows------ >>> runStdoutLoggingT $ runKleisli fLogging 5--- [Info] Calculating +2 of 5 => 7--- [Info] Calculating *3 of 7 => 21--- [Info] Calculating *4 of 7 => 28--- [Info] Calculating sum of 21 and 28 => 49--- 49------ We are now ready to consider an example with derivatives.--- Let us calculate a simple example as follows------ \[---  \frac{d}{dx} \mathrm{f} (e^x) = e^x f'(e^x)--- \]------ We define symbolic function @f@ by------ @---  loggingBackpropExpr :: String -> BackpropFunc SimpleExpr SimpleExpr--- @------ and the entire derivative is------ >>> runStdoutLoggingT $ runKleisli (derivative (exp >>> loggingBackpropExpr "f")) (variable "x")--- [Info] Calculating exp of x => exp(x)--- [Info] Calculating f of exp(x) => f(exp(x))--- [Info] Calculating f' of exp(x) => f'(exp(x))--- [Info] Calculating multiplication of 1 and f'(exp(x)) => 1·f'(exp(x))--- [Info] Calculating multiplication of 1·f'(exp(x)) and exp(x) => (1·f'(exp(x)))·exp(x)--- (1·f'(exp(x)))·exp(x)------ For illustration we can set 'f = sin' and 'x=2'------ \[---  \left. \frac{d}{dx} \sin (e^x) \right|_{x=2} = e^2 \cos (e^2)--- \]------ >>> runStdoutLoggingT $ runKleisli (derivative (exp >>> sin)) (2 :: Float)--- [Info] Calculating exp of 2.0 => 7.389056--- [Info] Calculating sin of 7.389056 => 0.893855--- [Info] Calculating cos of 7.389056 => 0.44835615--- [Info] Calculating multiplication of 1.0 and 0.44835615 => 0.44835615--- [Info] Calculating multiplication of 0.44835615 and 7.389056 => 3.312929--- 3.312929------ The first thing to mention in these logs is that the last forward step--- @sin(exp x)@--- is still computed, unlike the examples from the previous section.--- This is due to the monadic nature of the calculation chain, that must disappear as soon as we return to--- @(->)@ from 'Kleisli' @m@.------ The second thing to mention here is that the exponent--- @exp x@--- is calculated only once thanks to the cache term passed from the `forward` to the `backward` method.
− src/IsomorphismClass/Extra.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  IsomorphismClass.Extra--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Extra instances for 'IsomorphicTo' typeclass from 'isomorphism-class' package.-module IsomorphismClass.Extra () where--#if MIN_VERSION_isomorphism_class(0,3,0)-#else-import Control.Category (id)-#endif-import Data.Void (Void, absurd)-import IsomorphismClass (IsomorphicTo, to)-import Prelude (Either (Left, Right), fst, snd)--#if MIN_VERSION_isomorphism_class(0,3,0)-#else-instance {-# INCOHERENT #-} IsomorphicTo a a where-  to = id-#endif---- Type products--instance {-# INCOHERENT #-} IsomorphicTo a (a, ()) where-  to = fst--instance {-# INCOHERENT #-} IsomorphicTo (a, ()) a where-  to = (,())--instance {-# INCOHERENT #-} IsomorphicTo a ((), a) where-  to = snd--instance {-# INCOHERENT #-} IsomorphicTo ((), a) a where-  to = ((),)---- | Type product commutativity------ ==== __Examples of usage__------ >>> import IsomorphismClass.Isomorphism (iso)--- >>> (iso :: (->) (a, b) (b, a)) (1, "x")--- ("x",1)-instance {-# INCOHERENT #-} IsomorphicTo (a, b) (b, a) where-  to (b, a) = (a, b)--instance {-# INCOHERENT #-} IsomorphicTo (a, (b, c)) ((a, b), c) where-  to ((a, b), c) = (a, (b, c))--instance {-# INCOHERENT #-} IsomorphicTo ((a, b), c) (a, (b, c)) where-  to (a, (b, c)) = ((a, b), c)--instance {-# INCOHERENT #-} IsomorphicTo ((a, b), (c, d)) ((a, c), (b, d)) where-  to ((a, c), (b, d)) = ((a, b), (c, d))---- instance {-# INCOHERENT #-} IsomorphicTo (a, (b, (c, d))) (a, ((c, d), b)) where---  to (a, ((c, d), b)) = (a, (b, (c, d)))------ instance {-# INCOHERENT #-} IsomorphicTo (a, ((c, d), b)) (a, (b, (c, d))) where---  to (a, (b, (c, d))) = (a, ((c, d), b))---- Type sums--instance {-# INCOHERENT #-} IsomorphicTo a (Either a Void) where-  to (Left a) = a-  to (Right a) = absurd a--instance {-# INCOHERENT #-} IsomorphicTo (Either a Void) a where-  to = Left---- | Type sum commutativity.------ ==== __Examples of usage__------ >>> import IsomorphismClass.Isomorphism (iso)--- >>> (iso :: (->) (Either a b) (Either b a)) (Left 1)--- Right 1--- >>> (iso :: (->) (Either a b) (Either b a)) (Right "x")--- Left "x"-instance {-# INCOHERENT #-} IsomorphicTo a (Either Void a) where-  to (Right a) = a-  to (Left a) = absurd a--instance {-# INCOHERENT #-} IsomorphicTo (Either Void a) a where-  to = Right--instance {-# INCOHERENT #-} IsomorphicTo (Either a b) (Either b a) where-  to (Left b) = Right b-  to (Right b) = Left b--instance {-# INCOHERENT #-} IsomorphicTo (Either a (Either b c)) (Either (Either a b) c) where-  to (Left (Left a)) = Left a-  to (Left (Right b)) = Right (Left b)-  to (Right c) = Right (Right c)--instance {-# INCOHERENT #-} IsomorphicTo (Either (Either a b) c) (Either a (Either b c)) where-  to (Left a) = Left (Left a)-  to (Right (Left b)) = Left (Right b)-  to (Right (Right c)) = Right c--instance {-# INCOHERENT #-} IsomorphicTo (Either (Either a b) (Either c d)) (Either (Either a c) (Either b d)) where-  to (Left (Left a)) = Left (Left a)-  to (Left (Right c)) = Right (Left c)-  to (Right (Left b)) = Left (Right b)-  to (Right (Right d)) = Right (Right d)---- instance {-# INCOHERENT #-} IsomorphicTo (Either a (Either b (Either c d))) (Either a (Either (Either c d) b)) where---  to (Left a) = Left a---  to (Right (Left b)) = Right (Right b)---  to (Right (Right (Left c))) =   Right---------  to (a, ((c, d), b)) = (a, (b, (c, d)))------ instance {-# INCOHERENT #-} IsomorphicTo (Either a (Either (Either c d) b)) (Either a (Either b (Either c d))) where---  to (a, (b, (c, d))) = (a, ((c, d), b))
− src/IsomorphismClass/Isomorphism.hs
@@ -1,79 +0,0 @@-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  IsomorphismClass.Isomorphism--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Isomorphism class and instances.-module IsomorphismClass.Isomorphism-  ( Isomorphism,-    iso,-  )-where--import Control.Applicative (pure)-import Control.Arrow (Kleisli (Kleisli))-import Control.Category ((.))-import Control.Comonad (Cokleisli (Cokleisli), Comonad, extract)-import Control.Monad (Monad)-import GHC.Base (Type)-import IsomorphismClass (IsomorphicTo, from, to)-import Prelude (($))---- | A generalization of isomorphism.--- Type argument @c@ is usually a category.-class Isomorphism (c :: Type -> Type -> Type) where-  -- | Categorical morphism that that is related to an isomorphism map from @a@ to @b@.-  iso :: IsomorphicTo a b => c a b---- | Trivial instance of 'Isomorphism' that is the map type @(->)@.------ ==== __Examples of usage__------ >>> import Prelude (Int, fst, Either (Right))--- >>> import Data.Void (Void)--- >>> import IsomorphismClass.Extra ()------ >>> (iso :: (->) (a, b) (b, a)) (1, "x")--- ("x",1)------ >>> (iso :: (->) (a, ()) a) (42, ())--- 42------ >>> (iso :: (->) (Either Void a) a) (Right 42)--- 42-instance Isomorphism (->) where-  iso :: IsomorphicTo a b => a -> b-  iso = from---- | Kleisli (monadic) instance of 'Isomorphism'.------ ==== __Examples of usage__------ >>> import Prelude (Int, fst, Either (Right))--- >>> import Data.Void (Void)--- >>> import Control.Arrow (runKleisli)--- >>> import IsomorphismClass.Extra ()------ >>> runKleisli (iso :: (Kleisli []) (a, b) (b, a)) (1, "x")--- [("x",1)]-instance Monad m => Isomorphism (Kleisli m) where-  iso :: IsomorphicTo a b => Kleisli m a b-  iso = Kleisli $ pure . to---- | Cokleisli (comonadic) instance of 'Isomorphism'.------ ==== __Examples of usage__------ >>> import Prelude (Int, fst, Either (Right), (+))--- >>> import Data.Void (Void)--- >>> import Control.Comonad (Cokleisli(Cokleisli), runCokleisli)--- >>> import Control.Comonad.Store (store, runStore, Store)--- >>> import IsomorphismClass.Extra ()------ >>> runCokleisli (iso :: (Cokleisli (Store Int)) (a, b) (b, a)) (store (\x -> (x + 1, x + 2)) 0)--- (2,1)-instance Comonad w => Isomorphism (Cokleisli w) where-  iso :: IsomorphicTo a b => Cokleisli w a b-  iso = Cokleisli $ to . extract
− src/NumHask/Extra.hs
@@ -1,39 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---- | Module    :  NumHask.Extra--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Additional orphan instances for--- [mumhusk](https://hackage.haskell.org/package/numhask)--- typeclasses.-module NumHask.Extra () where--import NumHask (Additive, zero, (+))-import Prelude hiding (Num, (+))--instance {-# INCOHERENT #-} Additive () where-  (+) = const-  zero = ()--instance {-# INCOHERENT #-} (Additive x, Additive y) => Additive (x, y) where-  zero = (zero, zero)-  (a, b) + (c, d) = (a + c, b + d)--instance {-# INCOHERENT #-} (Additive x, Additive y, Additive z) => Additive (x, y, z) where-  zero = (zero, zero, zero)-  (x1, y1, z1) + (x2, y2, z2) = (x1 + x2, y1 + y2, z1 + z2)--instance {-# INCOHERENT #-} (Additive x, Additive y, Additive z, Additive t) => Additive (x, y, z, t) where-  zero = (zero, zero, zero, zero)-  (x1, y1, z1, t1) + (x2, y2, z2, t2) = (x1 + x2, y1 + y2, z1 + z2, t1 + t2)--instance-  {-# INCOHERENT #-}-  (Additive x, Additive y, Additive z, Additive t, Additive s) =>-  Additive (x, y, z, t, s)-  where-  zero = (zero, zero, zero, zero, zero)-  (x1, y1, z1, t1, s1) + (x2, y2, z2, t2, s2) = (x1 + x2, y1 + y2, z1 + z2, t1 + t2, s1 + s2)
+ src/Numeric/InfBackprop.hs view
@@ -0,0 +1,195 @@+-- | Module    :  Data.Vector.InfBackpropExtra+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- | Module providing all functionality of the library.+-- It re-exports all important types and functions from submodules.+-- See the documentation of individual submodules for details.+module Numeric.InfBackprop+  ( -- * Common++    -- ** Base+    Tangent,+    Dual,+    Cotangent,+    CT,+    RevDiff (MkRevDiff, value, backprop),+    RevDiff',+    DifferentiableFunc,+    initDiff,+    call,+    derivativeOp,+    constDiff,+    scalarArg,+    scalarVal,+    autoArg,+    autoVal,+    stopDiff,+    simpleDifferentiableFunc,++    -- ** Relation to lens and profunctors+    toLensOps,+    toLens,+    fromLens,+    fromProfunctors,+    toProfunctors,+    fromVanLaarhoven,+    toVanLaarhoven,++    -- ** Derivative operators+    scalarArgDerivative,+    customArgDerivative,+    customValDerivative,+    scalarValDerivative,+    simpleDerivative,+    simpleValueAndDerivative,+    customArgValDerivative,++    -- * Differentiable types++    -- ** Tuple+    twoArgsDerivative,+    twoArgsDerivativeOverX,+    twoArgsDerivativeOverY,+    tupleDerivativeOverX,+    tupleDerivativeOverY,+    mkTupleArg,+    tupleArg,+    tupleArgDerivative,+    mkTupleVal,+    tupleVal,+    tupleValDerivative,++    -- ** Triple+    threeArgsToTriple,+    threeArgsDerivative,+    derivative3ArgsOverX,+    derivative3ArgsOverY,+    derivative3ArgsOverZ,+    tripleDerivativeOverX,+    tripleDerivativeOverY,+    tripleDerivativeOverZ,+    mkTripleArg,+    tripleArg,+    tripleArgDerivative,+    mkTripleVal,+    tripleVal,+    tripleValDerivative,++    -- ** Boxed Vector+    mkBoxedVectorArg,+    boxedVectorArg,+    boxedVectorArgDerivative,+    mkBoxedVectorVal,+    boxedVectorVal,+    boxedVectorValDerivative,++    -- ** Stream+    mkStreamArg,+    streamArg,+    streamArgDerivative,+    mkStreamVal,+    streamVal,+    streamValDerivative,++    -- ** FiniteSupportStream+    mkFiniteSupportStreamArg,+    finiteSupportStreamArg,+    finiteSupportStreamArgDerivative,+    mkFiniteSupportStreamVal,+    finiteSupportStreamVal,+    finiteSupportStreamValDerivative,++    -- ** Maybe+    maybeArg,+    mkMaybeArg,+    maybeArgDerivative,+    maybeVal,+    mkMaybeVal,+    maybeValDerivative,+  )+where++import Numeric.InfBackprop.Core+  ( CT,+    Cotangent,+    DifferentiableFunc,+    Dual,+    RevDiff (MkRevDiff, backprop, value),+    RevDiff',+    Tangent,+    autoArg,+    autoVal,+    boxedVectorArg,+    boxedVectorArgDerivative,+    boxedVectorVal,+    boxedVectorValDerivative,+    call,+    constDiff,+    customArgDerivative,+    customArgValDerivative,+    customValDerivative,+    derivative3ArgsOverX,+    derivative3ArgsOverY,+    derivative3ArgsOverZ,+    derivativeOp,+    finiteSupportStreamArg,+    finiteSupportStreamArgDerivative,+    finiteSupportStreamVal,+    finiteSupportStreamValDerivative,+    fromLens,+    fromProfunctors,+    fromVanLaarhoven,+    initDiff,+    maybeArg,+    maybeArgDerivative,+    maybeVal,+    maybeValDerivative,+    mkBoxedVectorArg,+    mkBoxedVectorVal,+    mkFiniteSupportStreamArg,+    mkFiniteSupportStreamVal,+    mkMaybeArg,+    mkMaybeVal,+    mkStreamArg,+    mkStreamVal,+    mkTripleArg,+    mkTripleVal,+    mkTupleArg,+    mkTupleVal,+    scalarArg,+    scalarArgDerivative,+    scalarVal,+    scalarValDerivative,+    simpleDerivative,+    simpleDifferentiableFunc,+    simpleValueAndDerivative,+    stopDiff,+    streamArg,+    streamArgDerivative,+    streamVal,+    streamValDerivative,+    threeArgsDerivative,+    threeArgsToTriple,+    toLens,+    toLensOps,+    toProfunctors,+    toVanLaarhoven,+    tripleArg,+    tripleArgDerivative,+    tripleDerivativeOverX,+    tripleDerivativeOverY,+    tripleDerivativeOverZ,+    tripleVal,+    tripleValDerivative,+    tupleArg,+    tupleArgDerivative,+    tupleDerivativeOverX,+    tupleDerivativeOverY,+    tupleVal,+    tupleValDerivative,+    twoArgsDerivative,+    twoArgsDerivativeOverX,+    twoArgsDerivativeOverY,+  )
+ src/Numeric/InfBackprop/Core.hs view
@@ -0,0 +1,3327 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}++-- | Module    :  Data.Vector.InfBackpropExtra+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Backpropagation differentiation core types and functions.+module Numeric.InfBackprop.Core+  ( -- * Common++    -- ** Base+    Tangent,+    Dual,+    Cotangent,+    CT,+    RevDiff (MkRevDiff, value, backprop),+    RevDiff',+    DifferentiableFunc,+    initDiff,+    call,+    derivativeOp,+    toLensOps,+    constDiff,+    StopDiff (stopDiff),+    HasConstant (constant),+    simpleDifferentiableFunc,++    -- ** Relation to lens and profunctors+    toLens,+    fromLens,+    fromProfunctors,+    toProfunctors,+    fromVanLaarhoven,+    toVanLaarhoven,++    -- ** Derivative operators+    AutoDifferentiableArgument,+    DerivativeRoot,+    DerivativeCoarg,+    DerivativeArg,+    AutoDifferentiableValue,+    DerivativeValue,+    autoArg,+    autoVal,+    sameTypeDerivative,+    simpleDerivative,+    simpleValueAndDerivative,+    customArgDerivative,+    customValDerivative,+    customArgValDerivative,++    -- * Differentiable functions++    -- ** Basic+    differentiableSum,+    differentiableSub,+    differentiableNegate,+    differentiableMult,+    differentiableDiv,+    differentiableRecip,+    differentiableMultAction,+    differentiableConv,++    -- ** Exponential and logarithmic functions+    differentiablePow,+    differentiableExp,+    differentiableLog,+    differentiableLogBase,+    differentiableSqrt,++    -- ** Trigonometric functions+    differentiableSin,+    differentiableCos,+    differentiableTan,+    differentiableSinh,+    differentiableCosh,+    differentiableTanh,+    differentiableAsin,+    differentiableAcos,+    differentiableAtan,+    differentiableAtan2,+    differentiableAsinh,+    differentiableAcosh,+    differentiableAtanh,++    -- * Differentiable types++    -- ** Scalar+    scalarArg,+    scalarVal,+    scalarArgDerivative,+    scalarValDerivative,++    -- ** Tuple+    mkTupleArg,+    tupleArg,+    tupleArgDerivative,+    tupleDerivativeOverX,+    tupleDerivativeOverY,+    twoArgsDerivative,+    twoArgsDerivativeOverX,+    twoArgsDerivativeOverY,+    mkTupleVal,+    tupleVal,+    tupleValDerivative,++    -- ** Triple+    threeArgsToTriple,+    tripleArg,+    mkTripleArg,+    tripleArgDerivative,+    tripleDerivativeOverX,+    tripleDerivativeOverY,+    tripleDerivativeOverZ,+    threeArgsDerivative,+    derivative3ArgsOverX,+    derivative3ArgsOverY,+    derivative3ArgsOverZ,+    mkTripleVal,+    tripleVal,+    tripleValDerivative,++    -- ** BoxedVector+    boxedVectorArg,+    mkBoxedVectorArg,+    boxedVectorArgDerivative,+    boxedVectorVal,+    mkBoxedVectorVal,+    boxedVectorValDerivative,++    -- ** Stream+    streamArg,+    mkStreamArg,+    streamArgDerivative,+    streamVal,+    mkStreamVal,+    streamValDerivative,++    -- ** FiniteSupportStream+    finiteSupportStreamArg,+    mkFiniteSupportStreamArg,+    finiteSupportStreamArgDerivative,+    finiteSupportStreamVal,+    mkFiniteSupportStreamVal,+    finiteSupportStreamValDerivative,++    -- ** Maybe+    maybeArg,+    mkMaybeArg,+    maybeArgDerivative,+    maybeVal,+    mkMaybeVal,+    maybeValDerivative,+  )+where++import Control.Applicative ((<$>), (<*>))+import Control.Comonad.Identity (Identity (Identity, runIdentity))+import Control.ExtendableMap (ExtandableMap, extendMap)+import qualified Control.Lens as CL+import Control.Monad.ST (runST)+import Data.Bifunctor (first)+import Data.Coerce (coerce)+import Data.Composition ((.:))+import Data.Finite (Finite)+import Data.FiniteSupportStream (FiniteSupportStream (MkFiniteSupportStream, toVector), cons, empty, head, singleton, tail, unsafeMap)+import Data.Function (on)+import Data.Functor.Compose (Compose (Compose, getCompose))+import Data.Functor.Const (Const (Const, getConst))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (xor)+import Data.Primitive (Prim)+import Data.Profunctor (Profunctor (dimap))+import Data.Profunctor.Strong (Costrong (unfirst, unsecond))+import Data.Proxy (Proxy (Proxy))+import Data.Stream (Stream)+import qualified Data.Stream as DS+import Data.Tuple (curry, fst, snd, uncurry)+import Data.Tuple.Extra ((***))+import Data.Type.Equality (type (~))+import qualified Data.Vector as DV+import qualified Data.Vector.Fixed.Boxed as DVFB+import Data.Vector.Fusion.Util (Box (Box, unBox))+import qualified Data.Vector.Generic as DVG+import Data.Vector.Generic.Base+  ( Vector+      ( basicLength,+        basicUnsafeCopy,+        basicUnsafeFreeze,+        basicUnsafeIndexM,+        basicUnsafeSlice,+        basicUnsafeThaw,+        elemseq+      ),+  )+import qualified Data.Vector.Generic.Base as DVGB+import qualified Data.Vector.Generic.Mutable as DVGM+import qualified Data.Vector.Generic.Mutable.Base as DVGBM+import qualified Data.Vector.Generic.Sized as DVGS+import qualified Data.Vector.Generic.Sized.Internal as DVGSI+import qualified Data.Vector.Primitive as DVP+import qualified Data.Vector.Unboxed as DVU+import qualified Data.Vector.Unboxed.Mutable as DVUM+import Data.Word (Word, Word16, Word32, Word64, Word8)+import Debug.SimpleExpr (SimpleExpr, SimpleExprF)+import Debug.SimpleExpr.Expr (SE, number)+import Debug.SimpleExpr.Utils.Algebra+  ( AlgebraicPower ((^^)),+    Convolution ((|*|)),+    IntegerPower,+    MultiplicativeAction ((*|)),+    (^),+  )+import Debug.SimpleExpr.Utils.Traced (Traced (MkTraced))+import Debug.Trace (trace)+import Foreign (oneBits)+import GHC.Base+  ( Applicative,+    Eq ((==)),+    Float,+    Functor,+    Int,+    Maybe (Just, Nothing),+    Ord (compare, max, min, (<), (<=), (>), (>=)),+    Type,+    const,+    flip,+    fmap,+    id,+    pure,+    return,+    undefined,+    ($),+    (++),+    (.),+    (<*>),+  )+import GHC.Generics (C, Generic, type (:.:) (unComp1))+import GHC.Integer (Integer)+import GHC.Natural (Natural)+import qualified GHC.Num as GHCN+import GHC.Real (Integral, fromIntegral, realToFrac, toInteger)+import qualified GHC.Real as GHCR+import GHC.Show (Show (show))+import GHC.TypeLits (KnownChar)+import GHC.TypeNats (KnownNat, Nat)+import GHC.Types (Int)+import NumHask+  ( Additive,+    AdditiveAction,+    Complex,+    Distributive,+    Divisive,+    ExpField,+    Field,+    FromInteger (fromInteger),+    FromIntegral,+    Multiplicative,+    Subtractive,+    TrigField,+    acos,+    acosh,+    asin,+    asinh,+    atan,+    atan2,+    atanh,+    cos,+    cosh,+    exp,+    fromIntegral,+    log,+    logBase,+    negate,+    one,+    pi,+    recip,+    sin,+    sinh,+    sqrt,+    tan,+    tanh,+    two,+    zero,+    (*),+    (**),+    (+),+    (-),+    (/),+  )+import NumHask.Data.Integral (FromInteger)+import Numeric.InfBackprop.Instances.NumHask ()+import Numeric.InfBackprop.Utils.SizedVector (BoxedVector, boxedVectorBasis, boxedVectorSum)+import Numeric.InfBackprop.Utils.Tuple (cross, cross3, curry3, fork, fork3, uncurry3)+import Optics (Lens, Lens', getting, lens, set, simple, view, (%))++-- | Converts a type into its tangent space type.+type family Tangent (a :: Type) :: Type++type instance Tangent Float = Float++type instance Tangent GHCN.Integer = GHCN.Integer++type instance Tangent SimpleExpr = SimpleExpr++type instance Tangent (a0, a1) = (Tangent a0, Tangent a1)++type instance Tangent (a0, a1, a2) = (Tangent a0, Tangent a1, Tangent a2)++type instance Tangent [a] = [Tangent a]++type instance Tangent (DVFB.Vec n a) = DVFB.Vec n (Tangent a)++type instance Tangent (DVGS.Vector v n a) = DVGS.Vector v n (Tangent a)++type instance Tangent (Stream a) = Stream (Tangent a)++type instance Tangent (FiniteSupportStream a) = FiniteSupportStream (Tangent a)++type instance Tangent (Maybe a) = Maybe (Tangent a)++type instance Tangent (Traced a) = Traced (Tangent a)++type instance Tangent (Complex a) = Complex (Tangent a)++-- | Converts a type into its dual space type.+type family Dual (x :: Type) :: Type++type instance Dual Float = Float++type instance Dual GHCN.Integer = GHCN.Integer++type instance Dual SimpleExpr = SimpleExpr++type instance Dual (a, b) = (Dual a, Dual b)++type instance Dual (a, b, c) = (Dual a, Dual b, Dual c)++type instance Dual [a] = [Dual a]++type instance Dual (DVFB.Vec n a) = DVFB.Vec n (Dual a)++type instance Dual (DVGS.Vector v n a) = DVGS.Vector v n (Dual a)++type instance Dual (Stream a) = FiniteSupportStream (Dual a)++type instance Dual (FiniteSupportStream a) = Stream (Dual a)++type instance Dual (SimpleExprF a) = SimpleExprF (Dual a)++type instance Dual (Maybe a) = Maybe (Dual a)++type instance Dual (Traced a) = Traced (Dual a)++type instance Dual (Complex a) = Complex (Dual a)++-- | Cotangent type alias.+type Cotangent a = Dual (Tangent a)++-- | Cotangent type alias.+type CT a = Cotangent a++-- | Base type for differentiable instances with the backpropagation.+--+-- ==== __Examples__+--+-- >>> :{+--  differentiableSin_ :: RevDiff t Float Float -> RevDiff t Float Float+--  differentiableSin_ (MkRevDiff v bp) = MkRevDiff (sin v) (bp . (cos v *))+-- :}+--+-- >>> value $ differentiableSin_ (MkRevDiff 0.0 id)+-- 0.0+--+-- >>> backprop (differentiableSin_ (MkRevDiff 0.0 id)) 1.0+-- 1.0+--+-- === `GHC.Num.Num` typeclass instance+--+-- This instance enables the use of standard numeric operations and literals+-- directly with `RevDiff` values, simplifying the syntax for+-- automatic differentiation computations.--+-- The instance supports `GHC.Num.Num` operations including arithmetic+-- operators @(+), (-), (*)@, comparison functions (`GHC.Num.abs`, `GHC.Num.signum`), and automatic+-- conversion from integer literals via `fromInteger`.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import GHC.Integer (Integer)+--+-- >>> x = variable "x"+--+-- ===== Using numeric literals in automatic differentiation+--+-- This instance allows `RevDiff` values to be created directly from integer+-- literals, eliminating the need for explicit conversion functions.+--+-- Consider computing the partial derivative:+--+-- \[+--  \left.\frac{\partial}{\partial y} (x \cdot y)\right|_{y=2}+-- \]+--+-- Without the `GHC.Num.Num` instance, we would need explicit conversion:+--+-- >>> simplify $ twoArgsDerivativeOverY (*) x (stopDiff $ number 2) :: SE+-- x+--+-- With the `GHC.Num.Num` instance for `RevDiff`, this simplifies to:+--+-- >>> simplify $ twoArgsDerivativeOverY (*) x (number 2) :: SE+-- x+--+-- And combined with the `GHC.Num.Num` instance for `SE`,+-- we achieve the most concise form:+--+-- >>> simplify $ twoArgsDerivativeOverY (*) x 2+-- x+--+-- This progression shows how the typeclass instances work together to enable+-- increasingly natural mathematical notation.+--+-- ===== Power function differentiation+--+-- The instance enables natural exponentiation syntax with automatic differentiation:+--+-- >>> x ** 3 :: SE+-- x^3+-- >>> simplify $ simpleDerivative (** 3) x :: SE+-- 3*(x^2)+-- >>> simplify $ simpleDerivative (simpleDerivative (** 3)) x :: SE+-- (2*x)*3+--+-- ===== Absolute value and signum functions+--+-- The instance provides symbolic differentiation for absolute value and signum:+--+-- >>> simplify $ simpleDerivative GHCN.abs (variable "x") :: SE+-- sign(x)+--+-- >>> simplify $ simpleDerivative GHCN.signum (variable "x") :: SE+-- 0+--+-- For numeric evaluation, the second derivative of absolute value at a point+-- gives the expected result:+--+-- >>> (simpleDerivative (simpleDerivative GHCN.abs)) (1 :: Float) :: Float+-- 0.0+--+-- Notice that the signum function returns zero for all values, including zero.+--+-- >>> simpleDerivative GHCN.signum (0 :: Float) :: Float+-- 0.0+--+-- >>> simplify $ (simpleDerivative (simpleDerivative GHCN.abs)) (variable "x") :: SE+-- 0+--+-- === `GHCR.Fractional` typeclass instance+--+-- Thank to this instance we can use numerical literals like '1.0', '2.0', etc.,+-- see the examples below.+--+-- ==== __Examples__+--+-- >>> import GHC.Float (Float)+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+--+-- >>> f x = 8 / x+-- >>> simpleDerivative f (2.0 :: Float)+-- -2.0+-- >>> simplify $ simpleDerivative f (variable "x") :: SE+-- -((8/x)/x)+data RevDiff a b c = MkRevDiff {value :: c, backprop :: b -> a}+  deriving (Generic)++-- | Type alias for common case where the backpropagation is in the cotangent space.+type RevDiff' a b = RevDiff (CT a) (CT b) b++type instance Tangent (RevDiff a b c) = RevDiff a (Tangent b) (Tangent c)++type instance Dual (RevDiff a b c) = RevDiff a (Dual b) (Dual c)++-- | Converts a differentiable function into a regular function.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable)+-- >>> import Debug.DiffExpr (unarySymbolicFunc)+--+-- >>> :{+--  differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float+--  differentiableCos_ (MkRevDiff v bp) = MkRevDiff (cos v) (bp . negate . (sin v *))+-- :}+--+-- >>> call differentiableCos_ 0.0+-- 1.0+--+-- >>> x = variable "x"+-- >>> f = unarySymbolicFunc "f"+-- >>> f x+-- f(x)+--+-- >>> call f x+-- f(x)+call :: (RevDiff' a a -> RevDiff' a b) -> a -> b+call f = value . f . initDiff++-- | Converts a differentiable function into into its derivative in the form of+-- multiplicative operator.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable)+-- >>> import Debug.DiffExpr (unarySymbolicFunc)+--+-- >>> :{+--   differentiableSin_ :: RevDiff t Float Float -> RevDiff t Float Float+--   differentiableSin_ (MkRevDiff v bp) = MkRevDiff (sin v) (bp . (cos v *))+-- :}+--+-- >>> (derivativeOp differentiableSin_ 0.0) 1.0+-- 1.0+--+-- >>> c = variable "c"+-- >>> x = variable "x"+-- >>> f = unarySymbolicFunc "f"+-- >>> f x+-- f(x)+-- >>> (derivativeOp f x) c+-- f'(x)*c+derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a+derivativeOp f = backprop . f . initDiff++-- | Converts a function into a pair of its value and backpropagation function,+-- which are the lense get and set functions, respectively.+toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca)+toLensOps f x = (y, bp)+  where+    MkRevDiff y bp = f $ initDiff x++-- | Creates a differentiable function from a function and its derivative.+-- This is a convenience function for defining new differentiable operations.+--+-- ==== __Examples__+--+-- >>> :{+--  differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float+--  differentiableCos_ = simpleDifferentiableFunc cos (negate . sin)+-- :}+--+-- >>> call differentiableCos_ 0.0+-- 1.0+--+-- >>> simpleDerivative differentiableCos_ 0.0+-- -0.0+simpleDifferentiableFunc ::+  (Multiplicative b) =>+  (b -> b) ->+  (b -> b) ->+  RevDiff a b b ->+  RevDiff a b b+simpleDifferentiableFunc f f' (MkRevDiff x bpc) = MkRevDiff (f x) (\cy -> bpc $ f' x * cy)++-- | Initializes a `MkRevDiff` instance with given value+-- and identity backpropagation function.+-- This is useful for starting the backpropagation chain.+--+-- ==== __Examples__+--+-- >>> :{+--   differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float+--   differentiableCos_ (MkRevDiff v bp) = MkRevDiff (cos v) (bp . negate . (sin v *))+-- :}+--+-- >>> value $ differentiableCos_ (initDiff 0.0)+-- 1.0+--+-- >>> backprop (differentiableCos_ (initDiff 0.0)) 1.0+-- -0.0+initDiff :: a -> RevDiff b b a+initDiff x = MkRevDiff x id++-- | Converts a differentiable function into a /law-breaking/ 'Lens'.+-- This is mutually inverse with 'fromLens'.+--+-- ==== __Examples__+--+-- >>> import Optics (Lens', lens, view, set, getting, (%))+-- >>> import Debug.SimpleExpr (variable, SE)+--+-- >>> sinLens = toLens sin :: Lens' SE SE+-- >>> x = variable "x"+-- >>> c = variable "c"+-- >>> (view . getting) sinLens x+-- sin(x)+-- >>> set sinLens c x+-- cos(x)*c+-- >>> squareLens = toLens (^2) :: Lens' SE SE+-- >>> (view . getting) (squareLens % sinLens) x+-- sin(x^2)+toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d+toLens f = lens (value . bp) (backprop . bp)+  where+    bp = f . initDiff++-- | Converts a /law-breaking/ 'Lens' into a differentiable function.+-- This is mutually inverse with 'toLens'.+--+-- ==== __Examples__+--+-- >>> import Optics (lens)+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+--+-- >>> sinV2 = fromLens $ lens sin (\x -> (cos x *))+-- >>> x = variable "x"+-- >>> c = variable "c"+-- >>> call sinV2 x+-- sin(x)+-- >>> simplify $ simpleDerivative sinV2 x :: SE+-- cos(x)+fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b+fromLens l (MkRevDiff x bp) = MkRevDiff ((view . getting) l x) (\cy -> bp $ set l cy x)++-- | Profunctor instance for `RevDiff`.+instance Profunctor (RevDiff t) where+  dimap :: (a -> b) -> (c -> d) -> RevDiff t b c -> RevDiff t a d+  dimap f g (MkRevDiff v bp) = MkRevDiff (g v) (bp . f)++-- | Costrong instance for `RevDiff`.+instance Costrong (RevDiff t) where+  unfirst :: RevDiff t (a, d) (b, d) -> RevDiff t a b+  unfirst (MkRevDiff v bp) = MkRevDiff (fst v) (bp . (,snd v))+  unsecond :: RevDiff t (d, a) (d, b) -> RevDiff t a b+  unsecond (MkRevDiff v bp) = MkRevDiff (snd v) (bp . (fst v,))++-- | Type `DifferentiableFunc`@ a b@ may be associated with the differentiable+-- functions from @a@ to @b@.+-- Composition `(.)` of+-- @DifferentiableFunc b c@ and @DifferentiableFunc a b@ is @DifferentiableFunc a c@+-- by definition.+--+-- See `fromProfunctors`, `toProfunctors`, `fromVanLaarhoven` and `fromVanLaarhoven`+-- for illustraing how to use this type.+--+-- ==== __Examples__+--+-- >>> :{+--  differentiableCos_ :: DifferentiableFunc Float Float+--  differentiableCos_ (MkRevDiff x bpc) = MkRevDiff (cos x) (bpc . ((negate $ sin x) *))+-- :}+--+-- >>> call differentiableCos_ 0.0+-- 1.0+--+-- >>> simpleDerivative differentiableCos_ 0.0+-- -0.0+type DifferentiableFunc a b = forall t. RevDiff t (CT a) a -> RevDiff t (CT b) b++-- Profunctor and Van Laarhoven representations.++-- | Transorfms profunctor (Costrong) map into a 'RevDiff' map.+-- Inverse of 'toProfunctors'.+fromProfunctors ::+  (forall p. (Costrong p) => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b+fromProfunctors = id++-- | Profunctor representation of the `RevDiff` like for lens map in the spirit of optics.+-- Inverse of `fromProfunctors`.+toProfunctors ::+  -- (RevDiff a a -> RevDiff a b) ->+  -- (RevDiff (CT a) (CT a) a -> RevDiff (CT a) (CT b) b) ->+  (Costrong p) =>+  DifferentiableFunc a b ->+  p (CT a) a ->+  p (CT b) b+toProfunctors f = unsecond . dimap (uncurry u) (fork id v)+  where+    v = call f+    u = derivativeOp f++-- Van Laarhoven representation of the `RevDiff` type.++-- | Converts a Van Laarhoven representation to a function over `RevDiff` types+-- Inverse of `toVanLaarhoven`.+fromVanLaarhoven ::+  forall a b.+  (forall f. (Functor f) => (b -> f (CT b)) -> a -> f (CT a)) ->+  DifferentiableFunc a b+-- RevDiff t a ->+-- RevDiff t b+fromVanLaarhoven vll (MkRevDiff x bpx) = MkRevDiff y (bpx . bp)+  where+    (y, bp) = getCompose $ vll (\y_ -> Compose (y_, id)) x++-- | Converts a function over `RevDiff` types into a Van Laarhoven representation.+-- Inverse of `fromVanLaarhoven`.+toVanLaarhoven ::+  (Functor f) =>+  -- (RevDiff a a -> RevDiff a b) ->+  DifferentiableFunc a b ->+  (b -> f (CT b)) ->+  a ->+  f (CT a)+toVanLaarhoven g f x = fmap bp (f y)+  where+    MkRevDiff y bp = g $ initDiff x++-- -- | Performs backpropagation starting from 'one' and returns the result.+-- -- In particular,+-- -- for constant functions, this will return zero since their derivative is zero.+-- --+-- -- ==== __Examples__+-- --+-- -- >>> diff $ initDiff (42.0 :: Float) :: Float+-- -- 1.0+-- --+-- -- >>> diff (constDiff 42.0 :: RevDiff Float Float Float) :: Float+-- -- 0.0+-- diff :: (Multiplicative b) => RevDiff a b c -> a+-- diff x = backprop x one++-- | Creates a constant differentiable function.+-- The derivative of a constant function is always zero.+--+-- ==== __Examples__+--+-- >>> value (constDiff 42.0 :: RevDiff' Float Float)+-- 42.0+--+-- >>> backprop (constDiff 42.0 :: RevDiff' Float Float) 1.0+-- 0.0+constDiff :: (Additive a) => c -> RevDiff a b c+constDiff x = MkRevDiff x (const zero)++-- | Derivative for a scalar-to-scalar function.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SimpleExpr)+-- >>> import Debug.DiffExpr (unarySymbolicFunc)+--+-- >>> simpleDerivative sin (0.0 :: Float)+-- 1.0+--+-- >>> x = variable "x"+--+-- >>> simplify $ simpleDerivative (^ 2) x+-- 2*x+--+-- >>> f = unarySymbolicFunc "f"+--+-- >>> simplify $ simpleDerivative f x :: SimpleExpr+-- f'(x)+simpleDerivative ::+  forall a b.+  (Multiplicative (CT b)) =>+  (RevDiff' a a -> RevDiff' a b) ->+  a ->+  CT a+simpleDerivative f x = backprop (f (initDiff x)) one++-- | Derivative of a function from any type to the same type.+-- The type structure of the input and output values must be the same.+--+-- ==== __Examples__+--+-- >>> f = sin :: TrigField a => a -> a+-- >>> f' = sameTypeDerivative f :: Float -> Float+--+-- >>> f' 0.0+-- 1.0+sameTypeDerivative ::+  (Multiplicative (CT a)) =>+  (RevDiff (CT a) (CT a) a -> RevDiff (CT a) (CT a) a) ->+  a ->+  CT a+sameTypeDerivative = simpleDerivative++-- | Returns both the value and the derivative for a scalar-to-scalar function.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SimpleExpr)+-- >>> import Debug.DiffExpr (unarySymbolicFunc)+--+-- >>> simpleValueAndDerivative sin (0.0 :: Float)+-- (0.0,1.0)+--+-- >>> x = variable "x"+-- >>> f = unarySymbolicFunc "f"+--+-- >>> simplify $ simpleValueAndDerivative f x :: (SimpleExpr, SimpleExpr)+-- (f(x),f'(x))+simpleValueAndDerivative ::+  forall a b.+  (Multiplicative (CT b)) =>+  (RevDiff' a a -> RevDiff' a b) ->+  a ->+  (b, CT a)+simpleValueAndDerivative f x = (value out, backprop out one)+  where+    out = f (initDiff x)++-- | Derivative of a function from any type to any type.+-- The type structure of the input and output values must be specified+-- in the first and second arguments, respectively.+-- The output value type of the derivative is infereced automatically.+--+-- ==== __Examples__+--+-- >>> :{+--    sphericToVec :: (TrigField a) =>+--      (a, a) -> BoxedVector 3 a+--    sphericToVec (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- >>> sphericToVec' = customArgValDerivative tupleArg boxedVectorVal sphericToVec+--+-- Here 'tupleArg' manifests that the argument type is a tuple.+-- The second term 'boxedVectorVal' specifies that the output value type is a boxed vector.+--+-- >>> sphericToVec' (0 :: Float, 0 :: Float)+-- Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]+customArgValDerivative ::+  (RevDiff (CT a) (CT a) a -> b) ->+  (c -> d) ->+  (b -> c) ->+  a ->+  d+customArgValDerivative argTerm valTerm f = valTerm . f . argTerm . initDiff++-- | Axulary type for building nested argument structure descriptors.+type RevDiffArg a b c d = RevDiff a b c -> d++-- | Typeclass needed for the automatic agrument descriptor derivation.+-- See instance implementations for `RevDiff`, tuple and `BoxedVector` below.+--+-- ==== __Examples__+--+-- >>> :{+--  sphericToVector :: (TrigField a) =>+--    (a, a) -> BoxedVector 3 a+--  sphericToVector (theta, phi) =+--    DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- >>> sphericToVector' = customArgValDerivative autoArg boxedVectorVal sphericToVector+-- >>> sphericToVector' (0 :: Float, 0 :: Float)+-- Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]+class+  (Additive (DerivativeRoot a), Additive (DerivativeCoarg a)) =>+  AutoDifferentiableArgument a+  where+  -- | Differentiable function root+  type DerivativeRoot a :: Type++  -- | Differentiable function coargument+  type DerivativeCoarg a :: Type++  -- | Differentiable functin argument+  type DerivativeArg a :: Type++  -- | Automatic argument descriptor.+  autoArg :: RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a++-- | `AutoDifferentiableArgument` instance for the scalar argument term.+instance+  (Additive a, Additive b) =>+  AutoDifferentiableArgument (RevDiff a b c)+  where+  type DerivativeRoot (RevDiff a b c) = a+  type DerivativeCoarg (RevDiff a b c) = b+  type DerivativeArg (RevDiff a b c) = c+  autoArg = id++-- | Typeclass needed for the automatic value term derivation.+--+-- ==== __Examples__+--+-- >>> :{+--    sphericToVector :: (TrigField a) =>+--      (a, a) -> BoxedVector 3 a+--    sphericToVector (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- >>> sphericToVector' = customArgValDerivative tupleArg autoVal sphericToVector+-- >>> sphericToVector' (0 :: Float, 0 :: Float)+-- Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]+class AutoDifferentiableValue a where+  -- | Differentiable function value type.+  type DerivativeValue a :: Type++  -- | Automatic value descriptor.+  autoVal :: a -> DerivativeValue a++-- | Scalar value term.+--+-- ==== __Examples__+--+-- >>> :{+--    product :: (Multiplicative a) => (a, a) -> a+--    product (x, y) = x * y+-- :}+--+-- >>> product' = customArgValDerivative tupleArg scalarVal product+--+-- >>> product' (2 :: Float, 3 :: Float)+-- (3.0,2.0)+--+-- >>> import Debug.SimpleExpr (variable, simplify, SimpleExpr)+-- >>> x = variable "x"+-- >>> y = variable "y"+-- >>> simplify $ product' (x, y) :: (SimpleExpr, SimpleExpr)+-- (y,x)+scalarVal ::+  (Multiplicative b) =>+  RevDiff a b c ->+  a+scalarVal (MkRevDiff _ bp) = bp one++-- | `AutoDifferentiableValue` instance for the scalar value term.+instance+  (Multiplicative b) =>+  AutoDifferentiableValue (RevDiff a b c)+  where+  type DerivativeValue (RevDiff a b c) = a+  autoVal :: RevDiff a b c -> a+  autoVal = scalarVal++-- | Derivative operator for a function with a specified argument type,+-- but with the value type derived automatically.+--+-- ==== __Examples__+--+-- >>> :{+--    sphericToVec :: (TrigField a) =>+--      (a, a) -> BoxedVector 3 a+--    sphericToVec (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- >>> sphericToVec' = customArgDerivative tupleArg sphericToVec+--+-- Here 'tupleArg' indicates that the argument type is a tuple.+--+-- >>> sphericToVec' (0 :: Float, 0 :: Float)+-- Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]+customArgDerivative ::+  (AutoDifferentiableValue c) =>+  (RevDiff (CT a) (CT a) a -> b) ->+  (b -> c) ->+  a ->+  DerivativeValue c+customArgDerivative arg = customArgValDerivative arg autoVal++-- | Derivative operator for a function with specified argument type+-- but automatically derived value type.+--+-- ==== __Examples__+--+-- >>> :{+--    sphericToVector :: (TrigField a) =>+--      (a, a) -> BoxedVector 3 a+--    sphericToVector (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- >>> sphericToVector' = customValDerivative boxedVectorVal sphericToVector+--+-- The term 'boxedVectorVal' specifies that the output value type is a boxed vector.+--+-- >>> sphericToVector' (0 :: Float, 0 :: Float)+-- Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]+customValDerivative ::+  ( DerivativeRoot b ~ CT (DerivativeArg b),+    DerivativeCoarg b ~ CT (DerivativeArg b),+    AutoDifferentiableArgument b+  ) =>+  (c -> d) ->+  (b -> c) ->+  DerivativeArg b ->+  d+customValDerivative = customArgValDerivative autoArg++-- Scalar++-- | Scalar (trivial) argument descriptor for differentiable functions.+--+-- ==== __Examples__+--+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+-- >>> import Debug.SimpleExpr (variable, SimpleExpr, simplify, SE)+--+-- >>> scalarArgDerivative = customArgDerivative scalarArg+--+-- >>> t = variable "t"+-- >>> :{+--   v :: SymbolicFunc  a => a -> BoxedVector 3 a+--   v t = DVGS.fromTuple (+--      unarySymbolicFunc "v_x" t,+--      unarySymbolicFunc "v_y" t,+--      unarySymbolicFunc "v_z" t+--    )+-- :}+--+-- >>> v t+-- Vector [v_x(t),v_y(t),v_z(t)]+--+-- >>> v' = simplify . scalarArgDerivative v :: SE -> BoxedVector 3 SE+-- >>> v' t+-- Vector [v_x'(t),v_y'(t),v_z'(t)]+scalarArg :: RevDiff a b c -> RevDiff a b c+scalarArg = id++-- | Derivative operator for a function from a scalar to any supported value type.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+--+-- >>> :{+--   f :: TrigField a => a -> (a, a)+--   f t = (cos t, sin t)+-- :}+--+-- >>> f' = scalarArgDerivative f+--+-- >>> f (0 :: Float)+-- (1.0,0.0)+-- >>> f' (0 :: Float)+-- (-0.0,1.0)+--+-- >>> t = variable "t"+-- >>> f t+-- (cos(t),sin(t))+-- >>> simplify $ scalarArgDerivative f t :: (SE, SE)+-- (-(sin(t)),cos(t))+scalarArgDerivative ::+  (AutoDifferentiableValue c) =>+  (RevDiff' a a -> c) ->+  a ->+  DerivativeValue c+scalarArgDerivative = customArgValDerivative id autoVal++-- | Derivative operator for a function+-- from any supported argument type to a scalar value.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+--+-- >>> :{+--   f :: Additive a => (a, a) -> a+--   f (x, y) = x + y+-- :}+--+-- >>> f (2 :: Float, 3 :: Float)+-- 5.0+-- >>> x = variable "x"+-- >>> y = variable "y"+-- >>> f (x, y)+-- x+y+--+-- >>> :{+--   f' :: (Additive a, Distributive (CT a)) => (a, a) -> (CT a, CT a)+--   f' = scalarValDerivative f+-- :}+--+-- >>> f' (2 :: Float, 3 :: Float)+-- (1.0,1.0)+-- >>> simplify $ f' (x, y) :: (SE, SE)+-- (1,1)+scalarValDerivative ::+  ( DerivativeRoot b ~ CT a,+    DerivativeCoarg b ~ CT a,+    DerivativeArg b ~ a,+    Multiplicative (CT c),+    AutoDifferentiableArgument b+  ) =>+  (b -> RevDiff d (CT c) c) ->+  a ->+  d+scalarValDerivative = customArgValDerivative autoArg scalarVal++-- RevDiff type instances++-- | `RevDiff` instance for the `Show` typeclass.+instance (Show (b -> a), Show c) => Show (RevDiff a b c) where+  show (MkRevDiff x bp) = "MkRevDiff " ++ show x ++ " " ++ show bp++-- | Typeclass for the automatic iterrupt of the backpropagation.+--+-- ==== __Examples__+--+-- >>> :{+--    simpleDerivative+--      (\x -> x * twoArgsDerivativeOverY (+) x (stopDiff (1 :: Float)))+--      (2024 :: Float)+-- :}+-- 1.0+class StopDiff a b where+  -- | Stops differentiation by converting a nested `RevDiff` type+  -- into a non-differentiable type.+  stopDiff :: a -> b++-- | Base case: stopping differentiation for the same type.+instance StopDiff a a where+  stopDiff = id++-- | Recursive case: stopping differentiation for `RevDiff` type.+instance+  (StopDiff a d, Additive b) =>+  StopDiff a (RevDiff b c d)+  where+  stopDiff = constDiff . stopDiff++-- | Typeclass for creating constant differentiable functions.+class HasConstant a b c d where+  constant :: Proxy a -> b -> c -> d++-- | Base case: constant function for the same type.+instance HasConstant a b a b where+  constant _ x _ = x++-- | Recursive case: constant function for `RevDiff` type.+instance+  forall a b c d e f t.+  (HasConstant a b c d, Additive t, e ~ CT c, f ~ CT d) =>+  HasConstant a b (RevDiff t e c) (RevDiff t f d)+  where+  constant _ x (MkRevDiff v _) = constDiff $ constant (Proxy @a) x v++-- | Differentiable version of sum `(+)` for the `RevDiff` type.+--+-- This function implements automatic differentiation for addition by applying+-- the sum rule:+-- \[+--  \frac{d}{dx} (f(x) + g(x)) = \frac{df(x)}{dx} + \frac{dg(x)}{dx}+-- \].+-- The gradient flows equally to+-- both operands during backpropagation.+differentiableSum ::+  (Additive c) =>+  RevDiff a (b, b) (c, c) ->+  RevDiff a b c+differentiableSum (MkRevDiff (x0, x1) bpc) =+  MkRevDiff (x0 + x1) (\cy -> bpc (cy, cy))++-- | `Additive` instance for the `RevDiff` type.+instance+  (Additive a, Additive c) =>+  Additive (RevDiff a b c)+  where+  zero = constDiff zero+  (+) = differentiableSum .: twoArgsToTuple++-- | Differentiable version of subtraction `(-)` for the `RevDiff` type.+--+-- Implements the difference rule:+-- \[+--  \frac{d}{dx} (f(x) - g(x)) = \frac{df(x)}{dx} - \frac{dg(x)}{dx}.+-- \]+-- Duringt the backpropagation, the gradient flows positively to the first operand+-- and negatively to the second operand.+differentiableSub ::+  (Subtractive b, Subtractive c) =>+  RevDiff a (b, b) (c, c) ->+  RevDiff a b c+differentiableSub (MkRevDiff (x0, x1) bpc) =+  MkRevDiff (x0 - x1) (\cy -> bpc (cy, negate cy))++-- | Differentiable version of sign change function `negate` for `RevDiff` type.+--+-- Implements the negation rule:+-- \[+--  \frac{d}{dx} (-f(x)) = -\frac{df(x)}{dx}.+-- \]+-- The gradient is simply+-- negated during backpropagation.+differentiableNegate ::+  (Subtractive a, Subtractive c) =>+  RevDiff a b c ->+  RevDiff a b c+differentiableNegate (MkRevDiff x bp) = MkRevDiff (negate x) (negate . bp)++-- | `Subtractive` instance for the `RevDiff` type.+instance+  ( Additive a,+    Subtractive a,+    Subtractive b,+    Subtractive c+  ) =>+  Subtractive (RevDiff a b c)+  where+  negate = differentiableNegate+  (-) = differentiableSub .: twoArgsToTuple++-- | Differentiable version of commutative multiplication `(*)` for the `RevDiff` type.+--+-- Implements the product rule:+-- \[+--  \frac{d}{dx} (f(x) \cdot g(x)) = f(x) \cdot \frac{d g(x)}{dx} + \frac{df(x)}{dx} \cdot g(x).+-- \]+-- Each operand receives the gradient multiplied by the value of the other operand.+differentiableMult ::+  (Multiplicative b) =>+  RevDiff a (b, b) (b, b) ->+  RevDiff a b b+differentiableMult (MkRevDiff (x0, x1) bpc) =+  MkRevDiff (x0 * x1) (\cy -> bpc (x1 * cy, x0 * cy))++-- | `Multiplicative` instance for the `RevDiff` type.+instance+  (Additive a, Multiplicative b) =>+  Multiplicative (RevDiff a b b)+  where+  one = constDiff one+  (*) = differentiableMult .: twoArgsToTuple++instance+  (MultiplicativeAction Integer b, MultiplicativeAction Integer cb) =>+  MultiplicativeAction Integer (RevDiff ct cb b)+  where+  c *| (MkRevDiff x bp) = MkRevDiff (c *| x) (bp . (c *|))++-- | Differentiable version of multiplicative action `(*|)` for the `RevDiff` type.+--+-- Implements the product rule for scalar \( f \)+-- and, for example, vector \( g_i \):+--+-- \[+--  \frac{d}{dx} \left( f(x) \cdot g_i(x) \right) =+--  f(x) \cdot \frac{d g_i(x)}{dx} + \frac{df(x)}{dx} \cdot g_i(x).+-- \]+-- Each operand receives the gradient multiplied by the value of the other operand.+differentiableMultAction ::+  (MultiplicativeAction a b, MultiplicativeAction a cb, Convolution b cb ca) =>+  RevDiff ct (ca, cb) (a, b) ->+  RevDiff ct cb b+differentiableMultAction (MkRevDiff (x, y) bpc) =+  MkRevDiff (x *| y) (\cz -> bpc (y |*| cz, x *| cz))++instance+  (MultiplicativeAction a b, MultiplicativeAction a cb, Convolution b cb ca, Additive ct) =>+  MultiplicativeAction (RevDiff ct ca a) (RevDiff ct cb b)+  where+  (*|) = differentiableMultAction .: twoArgsToTuple++-- | Differentiable version of convolution `(|*|)` for the `RevDiff` type.+--+-- Implements the product rule for, for example, vectors+-- \( f_i \)+-- and+-- \( g_i \):+--+-- \[+--  \frac{d}{dx} \sum_i f_i(x) \cdot g_i(x) =+--  \sum_i f_i(x) \cdot \frac{d g_i(x)}{dx} + \frac{d f_i(x)}{dx} \cdot g_i(x)+-- \]+-- Each operand receives the gradient multiplied by the value of the other operand.+differentiableConv ::+  (Convolution a b c, Convolution cc b ca, Convolution a cc cb) =>+  RevDiff ct (ca, cb) (a, b) ->+  RevDiff ct cc c+differentiableConv (MkRevDiff (x, y) bpc) =+  MkRevDiff (x |*| y) (\cz -> bpc (cz |*| y, x |*| cz))++instance+  (Convolution a b c, Convolution cc b ca, Convolution a cc cb, Additive ct) =>+  Convolution (RevDiff ct ca a) (RevDiff ct cb b) (RevDiff ct cc c)+  where+  (|*|) = differentiableConv .: twoArgsToTuple++-- | Differentiable version of division `(/)` for the `RevDiff` type.+--+-- Implements the quotient rule:+-- \[+--  \frac{d}{dx} (f(x)/g(x)) =+--  \frac{\frac{df(x)}{dx} \cdot g(x) - f(x) \cdot \frac{dg(x)}{dx}}{g^2(x)}.+-- \]+-- The numerator receives gradient divided by the denominator, while the+-- denominator receives negative gradient scaled by the quotient divided by itself.+differentiableDiv ::+  (Subtractive b, Divisive b) =>+  RevDiff a (b, b) (b, b) ->+  RevDiff a b b+differentiableDiv (MkRevDiff (x0, x1) bpc) =+  MkRevDiff (x0 / x1) (\cy -> bpc (cy / x1, negate $ x0 / x1 / x1 * cy))++-- | Differentiable version of `recip` for `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \frac{1}{f(x)} = -\frac{1}{f^2(x)} \cdot \frac{df(x)}{dx}.+-- \]+-- The gradient is scaled by the negative+-- square of the reciprocal.+differentiableRecip ::+  (Divisive b, Subtractive b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableRecip (MkRevDiff x bpc) = MkRevDiff r (bpc . negate . (r ^ 2 *))+  where+    r = recip x++-- | `Divisive` instance for the `RevDiff` type.+instance+  (Additive a, Divisive b, Subtractive b, IntegerPower b) =>+  Divisive (RevDiff a b b)+  where+  recip = differentiableRecip+  (/) = differentiableDiv .: twoArgsToTuple++-- | Differentiable version of exponentiation `(**)` for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} f^{g(x)}(x) = f^{g(x)}(x) \cdot (\log f(x) \cdot \frac{dg(x)}{dx} + \frac{g(x)}{f(x)} \cdot \frac{df(x)}{dx}),+-- \]+-- handling both base+-- and exponent dependencies in the gradient computation.+differentiablePow ::+  (ExpField b) =>+  RevDiff a (b, b) (b, b) ->+  RevDiff a b b+differentiablePow (MkRevDiff (x, p) bpc) =+  MkRevDiff xp (\cy -> bpc (p * (x ** (p - one)) * cy, log x * xp * cy))+  where+    xp = x ** p++-- | Differentiable version of `exp` for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \exp{f(x)} = \exp{f(x)} \cdot \frac{df(x)}{dx}.+-- \]+-- The exponential function is its own derivative,+-- making the gradient computation particularly elegant.+differentiableExp ::+  (ExpField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableExp (MkRevDiff x bp) = MkRevDiff y (bp . (y *))+  where+    y = exp x++-- | Differentiable version of natural logarithm for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \log \left| f(x) \right| = \frac{1}{f(x)} \cdot \frac{df(x)}{dx}.+-- \]+-- For real numbers, this computes+-- the derivative of+-- \(\log |x|\),+-- which is defined for all non-zero values.+--+-- Unsafety note: This function and derivative will raise an error if @f@ is zero, as the+-- logarithm and `recip` from @numhask@ is undefined at zero point.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+--+-- >>> simplify $ simpleDerivative differentiableLog (variable "x") :: SE+-- 1/x+differentiableLog ::+  (ExpField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableLog (MkRevDiff x bp) = MkRevDiff (log x) (bp . (/ x))++-- | Differentiable version of `logBase` for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \log_b f(x)+-- \]+-- where both base and argument may be differentiable.+-- Uses the change of base formula and applies the chain rule appropriately.+differentiableLogBase ::+  (ExpField b, IntegerPower b) =>+  RevDiff a (b, b) (b, b) ->+  RevDiff a b b+differentiableLogBase (MkRevDiff (b, x) bpc) =+  MkRevDiff+    (logX / logB)+    (\cy -> bpc (negate $ logX / (logB ^ 2) / b * cy, recip x / logB * cy))+  where+    logX = log x+    logB = log b++-- | Differentiable version of `sqrt` for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \sqrt{f(x)} = \frac{1}{2 \sqrt {f(x)}} \cdot \frac{df(x)}{dx}.+-- The gradient is scaled by the+-- reciprocal of twice the square root of the input.+differentiableSqrt ::+  (ExpField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableSqrt (MkRevDiff x bp) = MkRevDiff y (\cy -> bp $ recip (two * y) * cy)+  where+    y = sqrt x++-- | `ExpField` instance for the `RevDiff` type.+instance+  (ExpField b, Additive a, Subtractive a, IntegerPower b) =>+  ExpField (RevDiff a b b)+  where+  exp = differentiableExp+  log = differentiableLog+  (**) = differentiablePow .: twoArgsToTuple+  logBase = differentiableLogBase .: twoArgsToTuple+  sqrt = differentiableSqrt++-- | Differentiable version of `atan2` for the `RevDiff` type.+--+-- Computes the two-argument arctangent function:+-- \[+--  \mathrm{arctg2}(y, x) = \arctg\left(\frac{y}{x}\right)+-- \]+--+-- The gradient computation accounts for both arguments using the formula:+-- \[+--  \frac{d}{dx} \mathrm{arctg2}(f(x),g(x)) =+--  - \frac{g(x)}{f(x)^2+g(x)^2} \cdot \frac{df(x)}{dx}+--  + \frac{f(x)}{f(x)^2+g(x)^2} \cdot \frac{dg(x)}{dx}+-- \]+differentiableAtan2 ::+  (TrigField b, IntegerPower b) =>+  RevDiff a (b, b) (b, b) ->+  RevDiff a b b+differentiableAtan2 (MkRevDiff (y, x) bpc) =+  MkRevDiff+    (atan2 y x)+    (\cy -> bpc (x / r2 * cy, negate $ y / r2 * cy))+  where+    r2 = x ^ 2 + y ^ 2++instance+  ( AlgebraicPower Int a,+    MultiplicativeAction Int a,+    Multiplicative a+  ) =>+  AlgebraicPower Int (RevDiff c a a)+  where+  x ^^ n = f x -- differentiablePow .: twoArgsToTuple+    where+      f =+        simpleDifferentiableFunc+          (^^ n)+          (\x' -> n *| (x' ^^ (n - 1)))++-- (fromIntegral n * integralPow (n - one))++instance+  ( AlgebraicPower Integer a,+    MultiplicativeAction Integer a,+    Multiplicative a+  ) =>+  AlgebraicPower Integer (RevDiff c a a)+  where+  x ^^ n = f x+    where+      f =+        simpleDifferentiableFunc+          (^^ n)+          (\x' -> n *| (x' ^^ (n - 1)))++-- | Differentiable version of sine function for the `RevDiff` type.+--+-- Implements+-- \[+-- d\frac{d}{dx} \sin f(x) = \cos f(x) * \frac{df(x)}{dx}+-- \]+-- using the standard trigonometric derivative.+--+-- ==== __Examples__+--+-- >>> call differentiableSin 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableSin 0.0 :: Float+-- 1.0+differentiableSin ::+  (TrigField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableSin = simpleDifferentiableFunc sin cos++-- | Differentiable version of cosine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \cos f(x) = -\sin f(x) \cdot \frac{df(x)}{dx}+-- \]+-- using the standard trigonometric derivative.+--+-- ==== __Examples__+--+-- >>> call differentiableCos 0.0 :: Float+-- 1.0+-- >>> simpleDerivative differentiableCos 0.0 :: Float+-- -0.0+differentiableCos ::+  (TrigField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableCos = simpleDifferentiableFunc cos (negate . sin)++-- | Differentiable version of tangent function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d]{dx} \tg f(x) =+--  \sec^2 f(x) * \frac{df(x)}{dx} = \frac{1}{cos^2 f(x)} \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableTan 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableTan 0.0 :: Float+-- 1.0+differentiableTan ::+  (TrigField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableTan = simpleDifferentiableFunc tan ((^ (-2)) . cos)++-- | Differentiable version of arcsine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \arcsin f(x) = \frac{1}{\sqrt{1-f^2(x)}} \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableAsin 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableAsin 0.0 :: Float+-- 1.0+differentiableAsin ::+  (TrigField b, ExpField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAsin = simpleDifferentiableFunc asin (recip . sqrt . (one -) . (^ 2))++-- | Differentiable version of arccosine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \arccos f(x) = -\frac{1}{\sqrt{1-f^2(x)}} \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableAcos 0.0 :: Float+-- 1.5707964+-- >>> simpleDerivative differentiableAcos 0.0 :: Float+-- -1.0+differentiableAcos ::+  (TrigField b, ExpField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAcos =+  simpleDifferentiableFunc acos (negate . recip . sqrt . (one -) . (^ 2))++-- | Differentiable version of arctangent function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \mathrm{arctg} f(x) = \frac{1}{1 + f^2(x)} \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableAtan 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableAtan 0.0 :: Float+-- 1.0+differentiableAtan ::+  (TrigField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAtan = simpleDifferentiableFunc atan (recip . (one +) . (^ 2))++-- | Differentiable version of hyperbolic sine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \sinh f(x) = \cosh f(x) \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableSinh 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableSinh 0.0 :: Float+-- 1.0+differentiableSinh ::+  (TrigField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableSinh = simpleDifferentiableFunc sinh cosh++-- | Differentiable version of hyperbolic cosine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \mathrm{csch} f(x) = \mathrm{sh} f(x) \cdot \frac{df(x)}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableCosh 0.0 :: Float+-- 1.0+-- >>> simpleDerivative differentiableCosh 0.0 :: Float+-- 0.0+differentiableCosh ::+  (TrigField b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableCosh = simpleDifferentiableFunc cosh sinh++-- | Differentiable version of hyperbolic tangent function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \mathrm{th} f(x) =+--  \mathrm{sech}^2 f(x) \cdot \frac{df}{dx} = \frac{1}{\mathrm{ch}^2 f(x)} \cdot \frac{df}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableTanh 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableTanh 0.0 :: Float+-- 1.0+differentiableTanh ::+  (TrigField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableTanh = simpleDifferentiableFunc tanh ((^ (-2)) . cosh)++-- | Differentiable version of inverse hyperbolic sine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \DeclareMathOperator{\arcsh}{arcsh}+--  \frac{d}{dx} \arcsh f(x) = \frac{1}{\sqrt{1 + f^2 (x)}} \cdot \frac{df}{dx}.+-- \]+--+-- ==== __Examples__+--+-- >>> call differentiableAsinh 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableAsinh 0.0 :: Float+-- 1.0+differentiableAsinh ::+  (TrigField b, ExpField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAsinh = simpleDifferentiableFunc asinh (recip . sqrt . (one +) . (^ 2))++-- | Differentiable version of inverse hyperbolic cosine function for the `RevDiff` type.+--+-- Implements+-- \[+--  \DeclareMathOperator{\arcch}{arcch}+--  \frac{d}{dx} \arcch f(x) = \frac{1}{f^2(x) - 1} \cdot \frac{df}{dx}.+-- \]+differentiableAcosh ::+  (TrigField b, ExpField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAcosh = simpleDifferentiableFunc acosh (recip . sqrt . (one -) . (^ 2))++-- | Differentiable version of inverse hyperbolic tangent function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \arcth f(x) = \frac{1}{1 - f^2 (x)} \cdot \frac{df}{dx}.+--+-- ==== __Examples__+--+-- >>> call differentiableAtanh 0.0 :: Float+-- 0.0+-- >>> simpleDerivative differentiableAtanh 0.0 :: Float+-- 1.0+differentiableAtanh ::+  (TrigField b, IntegerPower b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAtanh = simpleDifferentiableFunc atanh (recip . (one -) . (^ 2))++-- | `TrigField` instance for the `RevDiff` type.+instance+  (Additive a, Subtractive a, ExpField b, TrigField b, IntegerPower b) =>+  TrigField (RevDiff a b b)+  where+  -- Constants+  pi = constDiff pi++  -- Basic trig functions+  sin = differentiableSin+  cos = differentiableCos+  tan = differentiableTan++  -- Inverse trig functions+  asin = differentiableAsin+  acos = differentiableAcos+  atan = differentiableAtan+  atan2 = differentiableAtan2 .: twoArgsToTuple++  -- Hyperbolic functions+  sinh = differentiableSinh+  cosh = differentiableCosh+  tanh = differentiableTanh++  -- Inverse hyperbolic functions+  asinh = differentiableAsinh+  acosh = differentiableAcosh+  atanh = differentiableAtanh++-- | Differentiable version of absolute value function for the `RevDiff` type.+--+-- Implements+-- \[+--  \frac{d}{dx} \left_| f(x) \right_| = \sign(f) \cdot \frac{df}{dx},+-- \]+-- where \( \sign(f) \) is the signum function.+-- The derivative is undefined at zero but returns zero in this implementation.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+--+-- >>> simplify $ simpleDerivative differentiableAbs (variable "x") :: SE+-- sign(x)+--+-- >>> simpleDerivative differentiableAbs (10 :: Float) :: Float+-- 1.0+-- >>> simpleDerivative differentiableAbs (-10 :: Float) :: Float+-- -1.0+-- >>> simpleDerivative differentiableAbs (0 :: Float) :: Float+-- 0.0+differentiableAbs ::+  (GHCN.Num b, Multiplicative b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableAbs (MkRevDiff x bpc) =+  MkRevDiff (GHCN.abs x) (bpc . (GHCN.signum x *))++-- | Differentiable version of signum function for the `RevDiff` type.+--+-- The signum function has derivative zero everywhere except at zero (where it's undefined).+-- This implementation returns zero for all inputs, including zero.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+--+-- >>> simplify $ simpleDerivative differentiableSign (variable "x") :: SE+-- 0+--+-- >>> simpleDerivative differentiableSign (10 :: Float) :: Float+-- 0.0+-- >>> simpleDerivative differentiableSign (-10 :: Float) :: Float+-- 0.0+-- >>> simpleDerivative differentiableSign (0 :: Float) :: Float+-- 0.0+differentiableSign ::+  (Additive a, GHCN.Num b) =>+  RevDiff a b b ->+  RevDiff a b b+differentiableSign (MkRevDiff x _) = constDiff $ GHCN.signum x++-- | `RevDiff` instance for the `GHC.Num.Num` typeclass.+instance+  ( Additive a,+    Subtractive a,+    GHCN.Num b,+    Subtractive b,+    Multiplicative b+  ) =>+  GHCN.Num (RevDiff a b b)+  where+  (+) = (GHCN.+)+  (-) = (GHCN.-)+  (*) = (GHCN.*)+  negate = differentiableNegate+  abs = differentiableAbs+  signum = differentiableSign+  fromInteger = constDiff . GHCN.fromInteger++-- | `RevDiff` instance of the `NumHask.Data.Integral.FromInteger` typeclass.+instance+  (FromInteger c, Additive a) =>+  FromInteger (RevDiff a b c)+  where+  fromInteger = constDiff . fromInteger++-- | `RevDiff` and `Int8` instance of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Int8, Additive a) =>+  FromIntegral (RevDiff a b c) Int8+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Int16` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Int16, Additive a) =>+  FromIntegral (RevDiff a b c) Int16+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Int32` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Int32, Additive a) =>+  FromIntegral (RevDiff a b c) Int32+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Int64` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Int64, Additive a) =>+  FromIntegral (RevDiff a b c) Int64+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Int` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Int, Additive a) =>+  FromIntegral (RevDiff a b c) Int+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Word8` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Word8, Additive a) =>+  FromIntegral (RevDiff a b c) Word8+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Word16` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Word16, Additive a) =>+  FromIntegral (RevDiff a b c) Word16+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Word32` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Word32, Additive a) =>+  FromIntegral (RevDiff a b c) Word32+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Word64` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Word64, Additive a) =>+  FromIntegral (RevDiff a b c) Word64+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Word` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Word, Additive a) =>+  FromIntegral (RevDiff a b c) Word+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Integer` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Integer, Additive a) =>+  FromIntegral (RevDiff a b c) Integer+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` and `Natural` instance+-- of the `NumHask.Data.Integral.FromIntegral` typeclass.+instance+  (FromIntegral c Natural, Additive a) =>+  FromIntegral (RevDiff a b c) Natural+  where+  fromIntegral = constDiff . NumHask.fromIntegral++-- | `RevDiff` instance for the `GHC.Real.Fractional` typeclass.+instance+  ( Additive a,+    Subtractive a,+    Subtractive b,+    Divisive b,+    GHCR.Fractional b,+    IntegerPower b+  ) =>+  GHCR.Fractional (RevDiff a b b)+  where+  (/) = differentiableDiv .: twoArgsToTuple+  recip = differentiableRecip+  fromRational = constDiff . GHCR.fromRational++-- | Transforms two `RevDiff` instances into a 'RevDiff' instances with a tuple.+-- Inverese operation is 'tupleArg'.+twoArgsToTuple ::+  (Additive a) =>+  RevDiff a b0 c0 ->+  RevDiff a b1 c1 ->+  RevDiff a (b0, b1) (c0, c1)+twoArgsToTuple (MkRevDiff x0 bpc0) (MkRevDiff x1 bpc1) =+  MkRevDiff (x0, x1) (\(cy0, cy1) -> bpc0 cy0 + bpc1 cy1)++-- | Tuple argument descriptor for differentiable functions.+-- Transforms a `RevDiff` instances of a tuple into a tuple of `RevDiff` instances.+-- This allows applying differentiable operations to both elements of the tuple.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   f :: Multiplicative a => (a, a) -> a+--   f (x, y) = x * y+-- :}+--+-- >>> :{+--   f' :: (Distributive a, CT a ~ a) => (a, a) -> (a, a)+--   f' = customArgDerivative tupleArg f+-- :}+--+-- >>> simplify $ f' (variable "x", variable "y")+-- (y,x)+tupleArg ::+  (Additive b0, Additive b1) =>+  RevDiff a (b0, b1) (c0, c1) ->+  (RevDiff a b0 c0, RevDiff a b1 c1)+tupleArg (MkRevDiff (x0, x1) bpc) =+  ( MkRevDiff x0 (\cy -> bpc (cy, zero)),+    MkRevDiff x1 (\cy -> bpc (zero, cy))+  )++-- | Tuple argument descriptor builder.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:sophisticated-45-argument-45-function-45-how-45-it-45-works)+-- for details and examples.+mkTupleArg ::+  (Additive b0, Additive b1) =>+  RevDiffArg a b0 c0 d0 ->+  RevDiffArg a b1 c1 d1 ->+  RevDiffArg a (b0, b1) (c0, c1) (d0, d1)+mkTupleArg f0 f1 = cross f0 f1 . tupleArg++-- | Tuple instance for `AutoDifferentiableArgument` typeclass.+-- It makes it possible to differntiate tuple argument funcitons.+instance+  ( AutoDifferentiableArgument a0,+    AutoDifferentiableArgument a1,+    DerivativeRoot a0 ~ DerivativeRoot a1+  ) =>+  AutoDifferentiableArgument (a0, a1)+  where+  type DerivativeRoot (a0, a1) = DerivativeRoot a0+  type DerivativeCoarg (a0, a1) = (DerivativeCoarg a0, DerivativeCoarg a1)+  type DerivativeArg (a0, a1) = (DerivativeArg a0, DerivativeArg a1)+  autoArg :: RevDiff (DerivativeRoot a0) (DerivativeCoarg a0, DerivativeCoarg a1) (DerivativeArg a0, DerivativeArg a1) -> (a0, a1)+  autoArg = mkTupleArg autoArg autoArg++-- | Tuple differentiable value builder+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1)+mkTupleVal = cross++-- | Tuple differentiable value descriptor.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+tupleVal ::+  (Multiplicative b0, Multiplicative b1) =>+  (RevDiff a0 b0 c0, RevDiff a1 b1 c1) ->+  (a0, a1)+tupleVal = mkTupleVal scalarVal scalarVal++-- | Tuple instance for `AutoDifferentiableValue` typeclass.+-- It makes it possible to differntiate tuple value funcitons.+instance+  (AutoDifferentiableValue a0, AutoDifferentiableValue a1) =>+  AutoDifferentiableValue (a0, a1)+  where+  type DerivativeValue (a0, a1) = (DerivativeValue a0, DerivativeValue a1)+  autoVal :: (a0, a1) -> (DerivativeValue a0, DerivativeValue a1)+  autoVal = mkTupleVal autoVal autoVal++-- | Differentiable operator for functions with tuple argument+-- and any supported by `AutoDifferentiableValue` value type.+-- This function is equivalent to 'twoArgsDerivative' up to the curring.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a+--   h (x, y) = f x * g y+-- :}+--+-- >>> f(x)*g(y)+-- f(x)*g(y)+--+-- >>> :{+--  h' :: (SE, SE) -> (SE, SE)+--  h' = simplify . tupleArgDerivative h+-- :}+--+-- >>> h' (x, y)+-- (f'(x)*g(y),g'(y)*f(x))+--+-- >>> :{+--  h'' :: (SE, SE) -> ((SE, SE), (SE, SE))+--  h'' = simplify . tupleArgDerivative (tupleArgDerivative h)+-- :}+--+-- >>> h'' (x, y)+-- ((f''(x)*g(y),g'(y)*f'(x)),(f'(x)*g'(y),g''(y)*f(x)))+tupleArgDerivative ::+  (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) =>+  ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) ->+  (a0, a1) ->+  DerivativeValue b+tupleArgDerivative = customArgDerivative tupleArg++-- | Differentiable operator for functions over tuple argument+-- with respect to the first argument.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a+--   h (x, y) = f x * g y+-- :}+--+-- >>> f(x)*g(y)+-- f(x)*g(y)+--+-- >>> :{+--  h' :: (SE, SE) -> SE+--  h' = simplify . tupleDerivativeOverX h+-- :}+--+-- >>> h' (x, y)+-- f'(x)*g(y)+--+-- >>> :{+--  h'' :: (SE, SE) -> SE+--  h'' = simplify . tupleDerivativeOverX (tupleDerivativeOverX h)+-- :}+--+-- >>> h'' (x, y)+-- f''(x)*g(y)+tupleDerivativeOverX ::+  (AutoDifferentiableValue b, Additive (CT a0)) =>+  ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) ->+  (a0, a1) ->+  DerivativeValue b+tupleDerivativeOverX f (x0, x1) =+  scalarArgDerivative (\x -> f (x, constDiff x1)) x0++-- | Differentiable operator for functions over tuple argument+-- with respect to the second argument.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a+--   h (x, y) = f x * g y+-- :}+--+-- >>> f(x)*g(y)+-- f(x)*g(y)+--+-- >>> :{+--  h' :: (SE, SE) -> SE+--  h' = simplify . tupleDerivativeOverY h+-- :}+--+-- >>> h' (x, y)+-- g'(y)*f(x)+--+-- >>> :{+--  h'' :: (SE, SE) -> SE+--  h'' = simplify . tupleDerivativeOverY (tupleDerivativeOverY h)+-- :}+--+-- >>> h'' (x, y)+-- g''(y)*f(x)+tupleDerivativeOverY ::+  (Additive (CT a1), AutoDifferentiableValue b) =>+  ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) ->+  (a0, a1) ->+  DerivativeValue b+tupleDerivativeOverY f (x0, x1) =+  scalarArgDerivative (\x -> f (constDiff x0, x)) x1++-- | Differentiable operator for functions over two arguments+-- and any supported by 'AutoDifferentiableValue' value type.+-- Equivalent to 'tupleArgDerivative' up to the curring.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => a -> a -> a+--   h x y = f x * g y+-- :}+--+-- >>> f(x)*g(y)+-- f(x)*g(y)+--+-- >>> :{+--  h' :: SE -> SE -> (SE, SE)+--  h' = simplify . twoArgsDerivative h+-- :}+--+-- >>> h' x y+-- (f'(x)*g(y),g'(y)*f(x))+--+-- >>> :{+--  h'' :: SE -> SE -> ((SE, SE), (SE, SE))+--  h'' = simplify . twoArgsDerivative (twoArgsDerivative h)+-- :}+--+-- >>> h'' x y+-- ((f''(x)*g(y),g'(y)*f'(x)),(f'(x)*g'(y),g''(y)*f(x)))+twoArgsDerivative ::+  (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) =>+  (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) ->+  a0 ->+  a1 ->+  DerivativeValue b+twoArgsDerivative f = curry (scalarArgDerivative $ uncurry f . tupleArg)++-- | Differentiable operator for functions over two arguments+-- with respect to the first argument.+-- Equivalent to `tupleDerivativeOverX` up to the curring.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => a -> a -> a+--   h x y = f x * g y+-- :}+--+-- >>> f(x)*g(y)+-- f(x)*g(y)+--+-- >>> :{+--  h' :: SE -> SE -> SE+--  h' = simplify . twoArgsDerivativeOverX h+-- :}+--+-- >>> h' x y+-- f'(x)*g(y)+--+-- >>> :{+--  h'' :: SE -> SE -> SE+--  h'' = simplify . twoArgsDerivativeOverX (twoArgsDerivativeOverX h)+-- :}+--+-- >>> h'' x y+-- f''(x)*g(y)+twoArgsDerivativeOverX ::+  (Additive (CT a0), AutoDifferentiableValue b) =>+  (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) ->+  a0 ->+  a1 ->+  DerivativeValue b+twoArgsDerivativeOverX f x0 x1 =+  scalarArgDerivative (\x -> f x (constDiff x1)) x0++-- | Differentiable operator for functions over two arguments+-- with respect to the second argument.+-- Equivalent to `tupleDerivativeOverY` up to the curring.+twoArgsDerivativeOverY ::+  (Additive (CT a1), AutoDifferentiableValue b) =>+  (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) ->+  a0 ->+  a1 ->+  DerivativeValue b+twoArgsDerivativeOverY f = scalarArgDerivative . f . constDiff++-- | Differentiable operator for functions with tuple value and any supported by+-- `AutoDifferentiableArgument` argument type.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+--+-- >>> :{+--  f :: TrigField a => a -> (a, a)+--  f x = (sin x, cos x)+-- :}+--+-- >>> f (variable "x")+-- (sin(x),cos(x))+--+-- >>> :{+--  f' :: SE -> (SE, SE)+--  f' = simplify . tupleValDerivative f+-- :}+--+-- >>> f' (variable "x")+-- (cos(x),-(sin(x)))+tupleValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c0,+    Multiplicative c1,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1)) ->+  DerivativeArg a ->+  (b0, b1)+tupleValDerivative = customValDerivative tupleVal++-- boxedVectorValDerivative ::+--   ( AutoDifferentiableArgument a,+--     Multiplicative c,+--     DerivativeCoarg a ~ CT (DerivativeArg a),+--     DerivativeRoot a ~ CT (DerivativeArg a)+--   ) =>+--   (a -> BoxedVector n (RevDiff b c d)) ->+--   DerivativeArg a ->+--   BoxedVector n b+-- boxedVectorValDerivative = customValDerivative boxedVectorVal++-- Triple++-- | Differentiable operator for functions over triple arguments+-- with respect to the first argument.+tripleDerivativeOverX ::+  (AutoDifferentiableValue b, Additive (CT a0)) =>+  ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) ->+  (a0, a1, a2) ->+  DerivativeValue b+tripleDerivativeOverX f (x0, x1, x2) =+  scalarArgDerivative+    (\x -> f (x, constDiff x1, constDiff x2))+    x0++-- | Differentiable operator for functions over triple arguments+-- with respect to the second argument.+tripleDerivativeOverY ::+  (AutoDifferentiableValue b, Additive (CT a1)) =>+  ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) ->+  (a0, a1, a2) ->+  DerivativeValue b+tripleDerivativeOverY f (x0, x1, x2) =+  scalarArgDerivative+    (\x -> f (constDiff x0, x, constDiff x2))+    x1++-- | Differentiable operator for functions over triple arguments+-- with respect to the third argument.+tripleDerivativeOverZ ::+  (AutoDifferentiableValue b, Additive (CT a2)) =>+  ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) ->+  (a0, a1, a2) ->+  DerivativeValue b+tripleDerivativeOverZ f (x0, x1, x2) =+  scalarArgDerivative+    (\x -> f (constDiff x0, constDiff x1, x))+    x2++-- | Transforms three `RevDiff` instances into a `RevDiff` instances of a triple.+-- The inverese operation is 'tripleArg'.+threeArgsToTriple ::+  (Additive a) =>+  RevDiff a b0 c0 ->+  RevDiff a b1 c1 ->+  RevDiff a b2 c2 ->+  RevDiff a (b0, b1, b2) (c0, c1, c2)+threeArgsToTriple (MkRevDiff x0 bpc0) (MkRevDiff x1 bpc1) (MkRevDiff x2 bpc2) =+  MkRevDiff (x0, x1, x2) (\(cy0, cy1, cy2) -> bpc0 cy0 + bpc1 cy1 + bpc2 cy2)++-- | Triple argument descriptor for differentiable functions.+-- Transforms a `RevDiff` instances of a triple into a triple of `RevDiff` instances.+-- This allows applying differentiable operations to each element of the triple.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   f :: Multiplicative a => (a, a, a) -> a+--   f (x, y, z) = x * y * z+-- :}+--+-- >>> :{+--   f' :: (Distributive a, CT a ~ a) => (a, a, a) -> (a, a, a)+--   f' = customArgDerivative tripleArg f+-- :}+--+-- >>> simplify $ f' (variable "x", variable "y", variable "z")+-- (y*z,x*z,x*y)+tripleArg ::+  (Additive b0, Additive b1, Additive b2) =>+  RevDiff a (b0, b1, b2) (c0, c1, c2) ->+  (RevDiff a b0 c0, RevDiff a b1 c1, RevDiff a b2 c2)+tripleArg (MkRevDiff (x0, x1, x2) bpc) =+  ( MkRevDiff x0 (\cx -> bpc (cx, zero, zero)),+    MkRevDiff x1 (\cy -> bpc (zero, cy, zero)),+    MkRevDiff x2 (\cz -> bpc (zero, zero, cz))+  )++-- | Triple argument builder.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:sophisticated-45-argument-45-function-45-how-45-it-45-works)+-- for details and examples for the tuple.+mkTripleArg ::+  (Additive b0, Additive b1, Additive b2) =>+  RevDiffArg a b0 c0 d0 ->+  RevDiffArg a b1 c1 d1 ->+  RevDiffArg a b2 c2 d2 ->+  RevDiffArg a (b0, b1, b2) (c0, c1, c2) (d0, d1, d2)+mkTripleArg f0 f1 f2 = cross3 f0 f1 f2 . tripleArg++-- | Triple instance for `AutoDifferentiableArgument` typeclass.+-- It makes it possible to differntiate triple argument funcitons.+instance+  ( AutoDifferentiableArgument a0,+    AutoDifferentiableArgument a1,+    AutoDifferentiableArgument a2,+    DerivativeRoot a0 ~ DerivativeRoot a1,+    DerivativeRoot a0 ~ DerivativeRoot a2+  ) =>+  AutoDifferentiableArgument (a0, a1, a2)+  where+  type DerivativeRoot (a0, a1, a2) = DerivativeRoot a0+  type DerivativeCoarg (a0, a1, a2) = (DerivativeCoarg a0, DerivativeCoarg a1, DerivativeCoarg a2)+  type DerivativeArg (a0, a1, a2) = (DerivativeArg a0, DerivativeArg a1, DerivativeArg a2)+  autoArg :: RevDiff (DerivativeRoot a0) (DerivativeCoarg a0, DerivativeCoarg a1, DerivativeCoarg a2) (DerivativeArg a0, DerivativeArg a1, DerivativeArg a2) -> (a0, a1, a2)+  autoArg = mkTripleArg autoArg autoArg autoArg++-- | Triple differentiable value builder+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples for tuple.+mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)+mkTripleVal = cross3++-- | Triple differentiable value descriptor.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+tripleVal ::+  (Multiplicative b0, Multiplicative b1, Multiplicative b2) =>+  (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) ->+  (a0, a1, a2)+tripleVal = mkTripleVal scalarVal scalarVal scalarVal++-- | Triple instance for `AutoDifferentiableValue` typeclass.+instance+  ( AutoDifferentiableValue a0,+    AutoDifferentiableValue a1,+    AutoDifferentiableValue a2+  ) =>+  AutoDifferentiableValue (a0, a1, a2)+  where+  type DerivativeValue (a0, a1, a2) = (DerivativeValue a0, DerivativeValue a1, DerivativeValue a2)+  autoVal :: (a0, a1, a2) -> (DerivativeValue a0, DerivativeValue a1, DerivativeValue a2)+  autoVal = mkTripleVal autoVal autoVal autoVal++-- | Differentiable operator for functions with triple argument+-- and any supported by `AutoDifferentiableValue` value type.+-- The output is a triple of corresponding partial derivatives.+-- This function is equivalent to 'threeArgsDerivative' up to the curring.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.SimpleExpr.Utils.Algebra (AlgebraicPower, square, MultiplicativeAction)+-- >>> import Debug.DiffExpr (SymbolicFunc)+--+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   z = variable "z"+--   norm :: (AlgebraicPower Integer a, Additive a) => (a, a, a) -> a+--   norm (x, y, z) = square x + square y + square z+-- :}+--+-- >>> norm (x, y, z)+-- ((x^2)+(y^2))+(z^2)+--+-- >>> :{+--  norm' :: (SE, SE, SE) -> (SE, SE, SE)+--  norm' = simplify . tripleArgDerivative norm+-- :}+--+-- >>> simplify $ norm' (x, y, z)+-- (2*x,2*y,2*z)+--+-- >>> :{+--  norm'' :: (SE, SE, SE) -> ((SE, SE, SE), (SE, SE, SE), (SE, SE, SE))+--  norm'' = simplify . tripleArgDerivative (tripleArgDerivative norm)+-- :}+--+-- >>> norm'' (x, y, z)+-- ((2,0,0),(0,2,0),(0,0,2))+tripleArgDerivative ::+  ( Additive (CT a0),+    Additive (CT a1),+    Additive (CT a2),+    AutoDifferentiableValue b+  ) =>+  ( ( RevDiff' (a0, a1, a2) a0,+      RevDiff' (a0, a1, a2) a1,+      RevDiff' (a0, a1, a2) a2+    ) ->+    b+  ) ->+  (a0, a1, a2) ->+  DerivativeValue b+tripleArgDerivative = customArgDerivative tripleArg++-- | Differentiable operator for functions over three argument.+-- and any supported by `AutoDifferentiableValue` value type.+-- The output is a triple of corresponding partial derivatives.+-- This function is equivalent to 'tripleArgDerivative' up to the curring.+threeArgsDerivative ::+  ( AutoDifferentiableValue b,+    Additive (CT a0),+    Additive (CT a1),+    Additive (CT a2)+  ) =>+  ( RevDiff' (a0, a1, a2) a0 ->+    RevDiff' (a0, a1, a2) a1 ->+    RevDiff' (a0, a1, a2) a2 ->+    b+  ) ->+  a0 ->+  a1 ->+  a2 ->+  DerivativeValue b+threeArgsDerivative f = curry3 (scalarArgDerivative $ uncurry3 f . tripleArg)++-- | Differentiable operator for functions over three argument+-- with respect to the first argument.+-- and any supported by `AutoDifferentiableValue` value type.+derivative3ArgsOverX ::+  (AutoDifferentiableValue b, Additive (CT a0)) =>+  (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) ->+  a0 ->+  a1 ->+  a2 ->+  DerivativeValue b+derivative3ArgsOverX f x0 x1 x2 =+  scalarArgDerivative+    (\x0' -> f x0' (constDiff x1) (constDiff x2))+    x0++-- | Differentiable operator for functions over three argument+-- with respect to the second argument.+-- and any supported by `AutoDifferentiableValue` value type.+derivative3ArgsOverY ::+  (AutoDifferentiableValue b, Additive (CT a1)) =>+  (RevDiff' a1 a0 -> RevDiff' a1 a1 -> RevDiff' a1 a2 -> b) ->+  a0 ->+  a1 ->+  a2 ->+  DerivativeValue b+derivative3ArgsOverY f x0 x1 x2 =+  scalarArgDerivative+    (\x1' -> f (constDiff x0) x1' (constDiff x2))+    x1++-- | Differentiable operator for functions over three argument+-- with respect to the third argument.+-- and any supported by `AutoDifferentiableValue` value type.+derivative3ArgsOverZ ::+  (AutoDifferentiableValue b, Additive (CT a2)) =>+  (RevDiff' a2 a0 -> RevDiff' a2 a1 -> RevDiff' a2 a2 -> b) ->+  a0 ->+  a1 ->+  a2 ->+  DerivativeValue b+derivative3ArgsOverZ f x0 x1 =+  scalarArgDerivative $ f (constDiff x0) (constDiff x1)++-- | Differentiable operator for functions with tuple value and any supported by+-- `AutoDifferentiableArgument` argument type.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+--+-- >>> :{+--  f :: (Multiplicative a, IntegerPower a) => a -> (a, a, a)+--  f x = (one, x^1, x^2)+-- :}+--+-- >>> f (variable "x")+-- (1,x^1,x^2)+--+-- >>> :{+--  f' :: SE -> (SE, SE, SE)+--  f' = simplify . tripleValDerivative f+-- :}+--+-- >>> f' (variable "x")+-- (0,1,2*x)+tripleValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c0,+    Multiplicative c1,+    Multiplicative c2,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1, RevDiff b2 c2 d2)) ->+  DerivativeArg a ->+  (b0, b1, b2)+tripleValDerivative = customValDerivative tripleVal++-- BoxedVector++-- | `BoxedVector` differentiable value builder+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+mkBoxedVectorVal :: (a -> b) -> BoxedVector n a -> BoxedVector n b+mkBoxedVectorVal = fmap++-- | `BoxedVector` instance for `AutoDifferentiableValue` typeclass.+instance+  (AutoDifferentiableValue a) =>+  AutoDifferentiableValue (BoxedVector n a)+  where+  type DerivativeValue (BoxedVector n a) = BoxedVector n (DerivativeValue a)+  autoVal :: BoxedVector n a -> BoxedVector n (DerivativeValue a)+  autoVal = mkBoxedVectorVal autoVal++-- | Boxed array differentiable value descriptor.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+--+-- >>> :{+--   v :: SymbolicFunc a => a -> BoxedVector 3 a+--   v t = DVGS.fromTuple (+--      unarySymbolicFunc "v_x" t,+--      unarySymbolicFunc "v_y" t,+--      unarySymbolicFunc "v_z" t+--    )+-- :}+--+-- >>> t = variable "t"+-- >>> v t+-- Vector [v_x(t),v_y(t),v_z(t)]+--+-- >>> v' = simplify . customValDerivative boxedVectorVal v :: SE -> BoxedVector 3 SE+-- >>> v' t+-- Vector [v_x'(t),v_y'(t),v_z'(t)]+boxedVectorVal ::+  (Multiplicative b) =>+  BoxedVector n (RevDiff a b c) ->+  BoxedVector n a+boxedVectorVal = mkBoxedVectorVal scalarVal++-- | Differentiable operator for functions with `BoxedVector` argument+-- and any supported by `AutoDifferentiableValue` value type.+-- The output is a `BoxedVector` instamce of corresponding drivatives.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+--+-- >>> :{+--   v :: SymbolicFunc a => a -> BoxedVector 3 a+--   v t = DVGS.fromTuple (+--      unarySymbolicFunc "v_x" t,+--      unarySymbolicFunc "v_y" t,+--      unarySymbolicFunc "v_z" t+--    )+-- :}+--+-- >>> t = variable "t"+-- >>> v t+-- Vector [v_x(t),v_y(t),v_z(t)]+--+-- >>> v' = simplify . boxedVectorValDerivative v :: SE -> BoxedVector 3 SE+-- >>> v' t+-- Vector [v_x'(t),v_y'(t),v_z'(t)]+boxedVectorValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> BoxedVector n (RevDiff b c d)) ->+  DerivativeArg a ->+  BoxedVector n b+boxedVectorValDerivative = customValDerivative boxedVectorVal++-- | Boxed vector argument descriptor for differentiable functions.+-- Transforms a `RevDiff` instances of a boxed vector into a boxed vectror+-- of `RevDiff` instances.+-- This allows applying differentiable operations to each element of the boxed Vector.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)+--+-- >>> :{+--   f :: Additive a => BoxedVector 3 a -> a+--   f = boxedVectorSum+-- :}+--+-- >>> :{+--   f' :: (Distributive a, CT a ~ a) => BoxedVector 3 a -> BoxedVector 3 a+--   f' = customArgDerivative boxedVectorArg f+-- :}+--+-- >>> simplify $ f' (DVGS.fromTuple (variable "x", variable "y", variable "z"))+-- Vector [1,1,1]+boxedVectorArg ::+  (Additive b, KnownNat n) =>+  RevDiff a (BoxedVector n b) (BoxedVector n c) ->+  BoxedVector n (RevDiff a b c)+boxedVectorArg (MkRevDiff array bpc) = DVGS.generate $ \k ->+  MkRevDiff (DVGS.index array k) (bpc . boxedVectorBasis k zero)++-- unpackBoxedVector ::+--   (Additive a, KnownNat n) =>+--   BoxedVector n (RevDiff a b c) ->+--   RevDiff a (BoxedVector n b) (BoxedVector n c)+-- unpackBoxedVector array =+--   MkRevDiff'+--     (fmap value array)+--     (boxedVectorSum . (fmap backprop array <*>))++-- | `BoxedVector` argument descriptor builder.+mkBoxedVectorArg ::+  (Additive b, KnownNat n) =>+  RevDiffArg a b c d ->+  RevDiffArg a (BoxedVector n b) (BoxedVector n c) (BoxedVector n d)+mkBoxedVectorArg f = fmap f . boxedVectorArg++-- | `BoxedVector` instance for `AutoDifferentiableArgument` typeclass.+instance+  ( AutoDifferentiableArgument a,+    KnownNat n+  ) =>+  AutoDifferentiableArgument (BoxedVector n a)+  where+  type DerivativeRoot (BoxedVector n a) = DerivativeRoot a+  type DerivativeCoarg (BoxedVector n a) = BoxedVector n (DerivativeCoarg a)+  type DerivativeArg (BoxedVector n a) = BoxedVector n (DerivativeArg a)+  autoArg :: RevDiff (DerivativeRoot a) (BoxedVector n (DerivativeCoarg a)) (BoxedVector n (DerivativeArg a)) -> BoxedVector n a+  autoArg = mkBoxedVectorArg autoArg++-- | Differentiable operator for functions with boxed array argument+-- and any supported by `AutoDifferentiableValue` value type.+-- The output is a boxed array of corresponding partial derivatives (i.e. gradient).+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc)+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector, boxedVectorSum)+-- >>> import Debug.SimpleExpr.Utils.Algebra (AlgebraicPower, (^))+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   z = variable "z"+--   r = DVGS.fromTuple (x, y, z) :: BoxedVector 3 SE+--   norm2 :: (AlgebraicPower Integer a, Additive a) => BoxedVector 3 a -> a+--   norm2 v = boxedVectorSum (v^2)+-- :}+--+-- >>> simplify $ norm2 r+-- ((x^2)+(y^2))+(z^2)+--+-- >>> :{+--  norm2' :: BoxedVector 3 SE -> BoxedVector 3 SE+--  norm2' = simplify . boxedVectorArgDerivative norm2+-- :}+--+-- >>> norm2' r+-- Vector [2*x,2*y,2*z]+--+-- >>> :{+--  norm2'' :: BoxedVector 3 SE -> BoxedVector 3 (BoxedVector 3 SE)+--  norm2'' = simplify . boxedVectorArgDerivative (boxedVectorArgDerivative norm2)+-- :}+--+-- >>> norm2'' r+-- Vector [Vector [2,0,0],Vector [0,2,0],Vector [0,0,2]]+boxedVectorArgDerivative ::+  (KnownNat n, AutoDifferentiableValue b, Additive (CT a)) =>+  (BoxedVector n (RevDiff' (BoxedVector n a) a) -> b) ->+  BoxedVector n a ->+  DerivativeValue b+boxedVectorArgDerivative = customArgDerivative boxedVectorArg++-- instance (HasSum (BoxedVector n c) d, KnownNat n) =>+--   HasSum (RevDiff a (BoxedVector n b) (BoxedVector n c)) (RevDiff a b d) where+--     sum (MkRevDiff vec bp) = MkRevDiff' (sum vec) (bp . DVGS.replicate)++-- ** Stream++-- | Stream differentiable value builder+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+mkStreamVal :: (a -> b) -> Stream a -> Stream b+mkStreamVal = fmap++-- | Stream value structure for differentiable functions.+--+-- ==== __Examples__+--+-- >>> import GHC.Base ((<>))+-- >>> import Data.Stream (Stream, fromList, take)+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+--+-- >>> :{+--   s :: SymbolicFunc a => a -> Stream a+--   s t = fromList [unarySymbolicFunc ("s_" <> show n) t | n <- [0..]]+-- :}+--+-- >>> t = variable "t"+-- >>> take 5 (s t)+-- [s_0(t),s_1(t),s_2(t),s_3(t),s_4(t)]+--+-- >>> :{+--   s' :: SE -> Stream SE+--   s' = simplify . customValDerivative streamVal s+-- :}+--+-- >>> take 5 (s' t)+-- [s_0'(t),s_1'(t),s_2'(t),s_3'(t),s_4'(t)]+streamVal ::+  (Multiplicative b) =>+  Stream (RevDiff a b c) ->+  Stream a+streamVal = mkStreamVal scalarVal++-- | `Stream` instance for `AutoDifferentiableValue` typeclass.+instance+  (AutoDifferentiableValue a) =>+  AutoDifferentiableValue (Stream a)+  where+  type DerivativeValue (Stream a) = Stream (DerivativeValue a)+  autoVal :: Stream a -> Stream (DerivativeValue a)+  autoVal = mkStreamVal autoVal++-- | Derivative operator for a function from any supported argument type to a Stream.+streamValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> Stream (RevDiff b c d)) ->+  DerivativeArg a ->+  Stream b+streamValDerivative = customValDerivative streamVal++-- | Stream argument descriptor for differentiable functions.+-- Transforms a `RevDiff` instances of a stream into a stream of `RevDiff` instances.+-- This allows applying differentiable operations to each element of the Stream.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import GHC.Base ((<>))+--+-- >>> :{+--   f :: Additive a => Stream a -> a+--   f = NumHask.sum . Data.Stream.take 4 :: Additive a => Data.Stream.Stream a -> a+-- :}+--+-- >>> :{+--   f' :: (Distributive a, CT a ~ a) => Stream a -> FiniteSupportStream a+--   f' = customArgDerivative streamArg f+-- :}+--+-- >>> s = Data.Stream.fromList [variable ("s_" <> show n) | n <- [0 :: Int ..]] :: Data.Stream.Stream SE+-- >>> simplify $ f' s+-- [1,1,1,1,0,0,0,...+streamArg ::+  (Additive b) =>+  RevDiff a (FiniteSupportStream b) (Stream c) ->+  Stream (RevDiff a b c)+streamArg (MkRevDiff x bpc) =+  DS.Cons+    (MkRevDiff x_head bpc_head)+    (streamArg (MkRevDiff x_tail bpc_tail))+  where+    x_head = DS.head x+    x_tail = DS.tail x+    bpc_head = bpc . singleton+    bpc_tail = bpc . cons zero++-- | Stream argument builder.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:sophisticated-45-argument-45-function-45-how-45-it-45-works)+-- for details and examples for the tuple.+mkStreamArg ::+  (Additive b) =>+  (RevDiff a b c -> d) ->+  RevDiff a (FiniteSupportStream b) (Stream c) ->+  Stream d+mkStreamArg f = fmap f . streamArg++-- | `Stream` instance for `AutoDifferentiableArgument` typeclass.+instance+  (AutoDifferentiableArgument a) =>+  AutoDifferentiableArgument (Stream a)+  where+  type DerivativeRoot (Stream a) = DerivativeRoot a+  type DerivativeCoarg (Stream a) = FiniteSupportStream (DerivativeCoarg a)+  type DerivativeArg (Stream a) = Stream (DerivativeArg a)+  autoArg :: RevDiff (DerivativeRoot a) (FiniteSupportStream (DerivativeCoarg a)) (Stream (DerivativeArg a)) -> Stream a+  autoArg = mkStreamArg autoArg++-- | Differentiable operator for functions with `Stream` argument+-- and any supported by `AutoDifferentiableValue` value type.+-- The output is a boxed array of corresponding partial derivatives (i.e. gradient).+--+-- ==== __Examples__+--+-- >>> import GHC.Base ((<>))+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc)+-- >>> import Data.Stream (Stream, fromList, take)+--+-- >>> s = fromList [variable ("s_" <> show n) | n <- [0 :: Int ..]] :: Stream SE+--+-- >>> take4Sum = NumHask.sum . take 4 :: Additive a => Stream a -> a+-- >>> simplify $ take4Sum s :: SE+-- s_0+(s_1+(s_2+s_3))+--+-- >>> :{+--  take4Sum' :: (Distributive a, CT a ~ a) =>+--    Stream a -> FiniteSupportStream (CT a)+--  take4Sum' = streamArgDerivative take4Sum+-- :}+--+-- >>> simplify $ take4Sum' s+-- [1,1,1,1,0,0,0,...+--+-- >>> :{+--  take4Sum'' :: (Distributive a, CT a ~ a) =>+--    Stream a -> FiniteSupportStream (FiniteSupportStream (CT a))+--  take4Sum'' = streamArgDerivative (streamArgDerivative take4Sum)+-- :}+--+-- >>> simplify $ take4Sum'' s+-- [[0,0,0,...,[0,0,0,...,[0,0,0,...,...+streamArgDerivative ::+  (AutoDifferentiableValue b, Additive (CT a)) =>+  (Stream (RevDiff' (Stream a) a) -> b) ->+  Stream a ->+  DerivativeValue b+streamArgDerivative = customArgDerivative streamArg++-- FiniteSupportStream++-- | Finite support stream differentiable value builder+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+-- It is expected that the argument function is linear or at least maps zero to zero.+mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b+mkFiniteSupportStreamVal = unsafeMap++-- | Finite support stream value structure for differentiable functions.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+-- >>> import Data.FiniteSupportStream (unsafeFromList, FiniteSupportStream)+--+-- >>> :{+--  fss :: (Multiplicative a, IntegerPower a) =>+--    a -> FiniteSupportStream a+--  fss t = unsafeFromList [t^3, t^2, t, one]+-- :}+--+-- >>> t = variable "t"+-- >>> fss t+-- [t^3,t^2,t,1,0,0,0,...+--+-- >>> :{+--   fss' :: SE -> FiniteSupportStream SE+--   fss' = simplify . customValDerivative finiteSupportStreamVal fss+-- :}+--+-- >>> (fss' t)+-- [3*(t^2),2*t,1,0,0,0,...+finiteSupportStreamVal ::+  (Multiplicative b) =>+  FiniteSupportStream (RevDiff a b c) ->+  FiniteSupportStream a+finiteSupportStreamVal = mkFiniteSupportStreamVal scalarVal++-- | `FiniteSupportStream` instance for `AutoDifferentiableValue` typeclass.+instance+  (AutoDifferentiableValue a) =>+  AutoDifferentiableValue (FiniteSupportStream a)+  where+  type DerivativeValue (FiniteSupportStream a) = FiniteSupportStream (DerivativeValue a)+  autoVal :: FiniteSupportStream a -> FiniteSupportStream (DerivativeValue a)+  autoVal = mkFiniteSupportStreamVal autoVal++-- | Derivative operator for a function from any supported argument type to+-- a `FiniteSupportStream` instance.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)+-- >>> import Data.FiniteSupportStream (unsafeFromList, FiniteSupportStream)+--+-- >>> :{+--  fss :: (Multiplicative a, IntegerPower a) =>+--    a -> FiniteSupportStream a+--  fss t = unsafeFromList [t^3, t^2, t, one]+-- :}+--+-- >>> t = variable "t"+-- >>> fss t+-- [t^3,t^2,t,1,0,0,0,...+--+-- >>> :{+--   fss' :: SE -> FiniteSupportStream SE+--   fss' = simplify . finiteSupportStreamValDerivative fss+-- :}+--+-- >>> fss' t+-- [3*(t^2),2*t,1,0,0,0,...+finiteSupportStreamValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> FiniteSupportStream (RevDiff b c d)) ->+  DerivativeArg a ->+  FiniteSupportStream b+finiteSupportStreamValDerivative = customValDerivative finiteSupportStreamVal++-- | Finite support stream argument descriptor for differentiable functions.+-- Transforms a `RevDiff` instances of a finite support stream into+-- a finite support stream of `RevDiff` instances.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, SE, simplify)+-- >>> import Data.FiniteSupportStream (unsafeFromList, toVector)+--+-- >>> :{+--   f :: Additive a => FiniteSupportStream a -> a+--   f = NumHask.sum . toVector+-- :}+--+-- >>> f (unsafeFromList [1, 2, 3])+-- 6+--+-- >>> :{+--   f' :: (Distributive a, CT a ~ a) => FiniteSupportStream a -> Stream a+--   f' = customArgDerivative finiteSupportStreamArg f+-- :}+--+-- >>> Data.Stream.take 5 $ f' (unsafeFromList [1, 2, 3])+-- [1,1,1,0,0]+finiteSupportStreamArg ::+  (Additive b) =>+  RevDiff a (Stream b) (FiniteSupportStream c) ->+  FiniteSupportStream (RevDiff a b c)+finiteSupportStreamArg (MkRevDiff (MkFiniteSupportStream arrX) bpc) =+  MkFiniteSupportStream $ DV.imap f arrX+  where+    f i x = MkRevDiff x (bpc . cStream i)+    cStream i cy = go 0+      where+        go n = DS.Cons (if i == n then cy else zero) (go (n + 1))++-- cons+--   (MkRevDiff' x_head bpc_head)+--   (finiteSupportStreamArg (MkRevDiff' x_tail bpc_tail))+-- where+--   x_head = trace "taking head" $ head x+--   x_tail = trace "taking tail" $ tail x+--   bpc_head = trace "taking bpc_head" $ bpc . DS.fromList . (: [])+--   bpc_tail = trace "taking bpc_tail" $ bpc . DS.Cons zero++-- | Finite support stream argument descriptor builder.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+-- It is expected that the argument function is linear or at least maps zero to zero.+mkFiniteSupportStreamArg ::+  (Additive b) =>+  (RevDiff a b c -> d) ->+  RevDiff a (Stream b) (FiniteSupportStream c) ->+  FiniteSupportStream d+mkFiniteSupportStreamArg f = unsafeMap f . finiteSupportStreamArg++-- | `FiniteSupportStream` instance for `AutoDifferentiableArgument` typeclass.+instance+  (AutoDifferentiableArgument a) =>+  AutoDifferentiableArgument (FiniteSupportStream a)+  where+  type DerivativeRoot (FiniteSupportStream a) = DerivativeRoot a+  type DerivativeCoarg (FiniteSupportStream a) = Stream (DerivativeCoarg a)+  type DerivativeArg (FiniteSupportStream a) = FiniteSupportStream (DerivativeArg a)+  autoArg :: RevDiff (DerivativeRoot a) (Stream (DerivativeCoarg a)) (FiniteSupportStream (DerivativeArg a)) -> FiniteSupportStream a+  autoArg = undefined++-- | Differentiable operator for functions that take a `FiniteSupportStream` argument+-- and return any value type supported by `AutoDifferentiableValue`.+-- The output is a stream of corresponding partial derivatives,+-- computing the gradient of the function with respect to each stream element.+-- See also+-- ["Tangent and Cotangent Spaces" tutorial section](Numeric-InfBackprop-Tutorial.html#g:how-45-it-45-works-45-tangent-45-space)+-- for the connection beetwen streams and finite support streams.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc)+-- >>> import Data.Stream (Stream, take)+-- >>> import Data.FiniteSupportStream (FiniteSupportStream, unsafeFromList, toVector)+-- >>> import NumHask (sum)+--+-- Define a finite support stream with support length 4 containing 4 symbolic variables.+--+-- >>> s = unsafeFromList [variable "s_0", variable "s_1", variable "s_2", variable "s_3"] :: FiniteSupportStream SE+-- >>> s+-- [s_0,s_1,s_2,s_3,0,0,0,...+--+-- Now we'll define a function that sums all elements of a finite support stream.+--+-- >>> finiteSupportStreamSum = sum . toVector :: Additive a => FiniteSupportStream a -> a+-- >>> simplify $ finiteSupportStreamSum s :: SE+-- s_0+(s_1+(s_2+s_3))+--+-- We compute the gradient+-- of this function.+--+-- >>> :{+--  finiteSupportStreamSum' :: (Distributive a, CT a ~ a) =>+--    FiniteSupportStream a -> Stream (CT a)+--  finiteSupportStreamSum' = finiteSupportStreamArgDerivative finiteSupportStreamSum+-- :}+--+-- Let's compute the gradient at point @s@. It is an infinite stream and we take first 7 elements:+--+-- >>> take 7 $ simplify $ finiteSupportStreamSum' s+-- [1,1,1,1,0,0,0]+--+-- As expected,+-- the gradient is a stream with 1's in the first four positions (corresponding+-- to our four variables and the fixed support length 4) and 0's elsewhere:+--+-- We can compute the second derivative (Hessian matrix) that is stream of streams+-- in our case.+--+-- >>> :{+--  finiteSupportStreamSum'' :: (Distributive a, CT a ~ a) =>+--    FiniteSupportStream a -> Stream (Stream (CT a))+--  finiteSupportStreamSum'' = finiteSupportStreamArgDerivative (finiteSupportStreamArgDerivative finiteSupportStreamSum)+-- :}+--+-- All second derivatives should all be zero. We take first 7 rows and 4 columns of the inifinite Hessian matrix:+--+-- >>> take 7 $ fmap (take 4) $ simplify $ finiteSupportStreamSum'' s+-- [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]+finiteSupportStreamArgDerivative ::+  (AutoDifferentiableValue b, Additive (CT a)) =>+  (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) ->+  FiniteSupportStream a ->+  DerivativeValue b+finiteSupportStreamArgDerivative = customArgDerivative finiteSupportStreamArg++-- | Maybe differentiable value builder.+-- Creates a mapping function for Maybe types.+-- See [this tutorial section]+-- (Numeric-InfBackprop-Tutorial.html#g:multivalued-45-function-45-how-45-it-45-works)+-- for details and examples.+mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b+mkMaybeVal = fmap++-- | `Maybe` value structure for differentiable functions.+-- Extracts the derivative with respect to the original function for `Maybe` types.+--+-- ==== __Examples__+--+-- >>> :{+--  class SafeRecip a where+--    safeRecip :: a -> Maybe a+--  instance SafeRecip Float where+--    safeRecip x = if x == 0.0 then Nothing else Just (recip x)+--  instance (SafeRecip b, Subtractive b, Multiplicative b, IntegerPower b) =>+--    SafeRecip (RevDiff a b b) where+--      safeRecip (MkRevDiff v bp) =+--        fmap (\r -> MkRevDiff r (bp . negate . (r^2 *))) (safeRecip v)+-- :}+--+-- >>> safeRecip (2.0 :: Float) :: Maybe Float+-- Just 0.5+-- >>> safeRecip (0.0 :: Float) :: Maybe Float+-- Nothing+--+-- >>> customValDerivative maybeVal safeRecip (2.0 :: Float)+-- Just (-0.25)+-- >>> customValDerivative maybeVal safeRecip (0.0 :: Float)+-- Nothing+maybeVal ::+  (Multiplicative b) =>+  Maybe (RevDiff a b c) ->+  Maybe a+maybeVal = mkMaybeVal scalarVal++-- | `Maybe` instance of `AutoDifferentiableValue`.+instance+  (AutoDifferentiableValue a) =>+  AutoDifferentiableValue (Maybe a)+  where+  type DerivativeValue (Maybe a) = Maybe (DerivativeValue a)+  autoVal :: Maybe a -> Maybe (DerivativeValue a)+  autoVal = mkMaybeVal autoVal++-- | Argument descriptor for differentiable functions with optional argument.+-- Transforms a `RevDiff` instances of an otional type into+-- an optional of `RevDiff` instances.+-- This allows applying differentiable operations to the optiona value.++-- | Argument descriptor for differentiable functions with optional (`Maybe`) values.+--+-- Transforms a `RevDiff` instance containing an optional type into an optional+-- `RevDiff` instance. This transformation enables applying differentiable+-- operations to values that may or may not be present, while preserving+-- gradient flow when values exist.+--+-- When the wrapped value is `Just x`, the function extracts the value and+-- wraps it in a new `RevDiff` instance with appropriately transformed+-- backpropagation. When the value is `Nothing`, the result is `Nothing`,+-- effectively short-circuiting the computation.+--+-- ==== __Examples__+--+-- >>> :{+--  f :: Additive a => Maybe a -> a+--  f (Just x) = x+--  f Nothing = zero+-- :}+--+-- >>> customArgDerivative maybeArg f (Just 3 :: Maybe Float) :: Maybe Float+-- Just 1.0+maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c)+maybeArg (MkRevDiff maybeX bpc) = case maybeX of+  Just x -> Just (MkRevDiff x (bpc . Just))+  Nothing -> Nothing++-- | Maybe argument builder.+-- Applies a function to `Maybe` value obtained from a `RevDiff`.+mkMaybeArg ::+  (RevDiff a b c -> d) -> RevDiff a (Maybe b) (Maybe c) -> Maybe d+mkMaybeArg f = fmap f . maybeArg++-- | `Maybe` instance of `AutoDifferentiableArgument`.+instance+  (AutoDifferentiableArgument a) =>+  AutoDifferentiableArgument (Maybe a)+  where+  type DerivativeRoot (Maybe a) = DerivativeRoot a+  type DerivativeCoarg (Maybe a) = Maybe (DerivativeCoarg a)+  type DerivativeArg (Maybe a) = Maybe (DerivativeArg a)+  autoArg :: RevDiff (DerivativeRoot a) (Maybe (DerivativeCoarg a)) (Maybe (DerivativeArg a)) -> Maybe a+  autoArg = mkMaybeArg autoArg++-- | Differentiable operator for functions that take a `Maybe` (a value or none) argument+-- and return any value type supported by `AutoDifferentiableValue`.+-- The output is `Maybe` of corresponding derivatives over the inner type.+--+-- ==== __Examples__+--+-- >>> import Debug.SimpleExpr (variable, simplify, SE)+-- >>> import Debug.DiffExpr (SymbolicFunc)+-- >>> import qualified GHC.Num as GHCN+--+-- >>> :{+--  maybeF :: TrigField a => Maybe a -> a+--  maybeF (Just x) = sin x+--  maybeF Nothing = zero+-- :}+--+-- >>> maybeF (Just 0.0 :: Maybe Float)+-- 0.0+--+-- >>> maybeF (Nothing :: Maybe Float)+-- 0.0+--+-- >>> maybeArgDerivative maybeF (Just 0.0 :: Maybe Float)+-- Just 1.0+--+-- >>> maybeArgDerivative maybeF (Nothing :: Maybe Float)+-- Just 0.0+maybeArgDerivative ::+  (AutoDifferentiableValue b) =>+  (Maybe (RevDiff' (Maybe a) a) -> b) ->+  Maybe a ->+  DerivativeValue b+maybeArgDerivative = customArgDerivative maybeArg++-- | Derivative operator for functions with Maybe arguments.+-- This allows computing derivatives of functions that returns Maybe values as output,+-- handling the case when the value is Nothing appropriately.+--+-- ==== __Examples__+--+-- >>> :{+--  class SafeRecip a where+--    safeRecip :: a -> Maybe a+--  instance SafeRecip Float where+--    safeRecip x = if x == 0.0 then Nothing else Just (recip x)+--  instance (SafeRecip b, Subtractive b, Multiplicative b, IntegerPower b) =>+--    SafeRecip (RevDiff a b b) where+--      safeRecip (MkRevDiff v bp) =+--        fmap (\r -> MkRevDiff r (bp . negate . (r^2 *))) (safeRecip v)+-- :}+--+-- >>> safeRecip (2.0 :: Float) :: Maybe Float+-- Just 0.5+-- >>> safeRecip (0.0 :: Float) :: Maybe Float+-- Nothing+--+-- >>> maybeValDerivative safeRecip (2.0 :: Float)+-- Just (-0.25)+-- >>> maybeValDerivative safeRecip (0.0 :: Float)+-- Nothing+maybeValDerivative ::+  ( AutoDifferentiableArgument a,+    Multiplicative c,+    DerivativeCoarg a ~ CT (DerivativeArg a),+    DerivativeRoot a ~ CT (DerivativeArg a)+  ) =>+  (a -> Maybe (RevDiff b c d)) ->+  DerivativeArg a ->+  Maybe b+maybeValDerivative = customValDerivative maybeVal
+ src/Numeric/InfBackprop/Instances/NumHask.hs view
@@ -0,0 +1,423 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-- |+-- Module    :  Numeric.InfBackprop.Instances.NumHask+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Orphane instances for+-- [numhask](https://hackage.haskell.org/package/numhask)+-- typeclasses.+module Numeric.InfBackprop.Instances.NumHask () where++{- HLINT ignore "Use fewer imports" -}++import Control.Applicative (liftA2)+import Data.Bifunctor (bimap)+import qualified Data.Stream as DS+import qualified Data.Vector.Generic as DVG+import qualified Data.Vector.Generic.Sized as DVGS+import GHC.Base (Functor (fmap), Maybe (Just))+import GHC.TypeNats (KnownNat)+import NumHask+  ( Additive,+    Divisive,+    ExpField,+    Multiplicative,+    Subtractive,+    TrigField,+    acos,+    acosh,+    asin,+    asinh,+    atan,+    atan2,+    atanh,+    cos,+    cosh,+    exp,+    log,+    logBase,+    negate,+    one,+    pi,+    recip,+    sin,+    sinh,+    sqrt,+    tan,+    tanh,+    zero,+    (*),+    (**),+    (+),+    (-),+    (/),+  )+import Numeric.InfBackprop.Utils.Tuple (biCross, biCross3, cross, cross3)++-- | Instances for NumHask classes for common data types.+-- These instances follow the standard lifting of operations to container types.+--+-- Note: These are orphan instances. Consider proposing them upstream to numhask.++-- | Tuple instance of `Additive` typecalss.+instance+  (Additive a0, Additive a1) =>+  Additive (a0, a1)+  where+  zero = (zero, zero)+  (+) = biCross (+) (+)++-- | Tuple instance of `Subtractive` typeclass.+instance+  (Subtractive a0, Subtractive a1) =>+  Subtractive (a0, a1)+  where+  negate (x0, x1) = (negate x0, negate x1)+  (-) = biCross (-) (-)++-- | Tuple instance of `Multiplicative` typeclass.+instance+  (Multiplicative a0, Multiplicative a1) =>+  Multiplicative (a0, a1)+  where+  one = (one, one)+  (*) = biCross (*) (*)++-- | Tuple instance of `Divisive` typeclass.+instance+  (Divisive a0, Divisive a1) =>+  Divisive (a0, a1)+  where+  recip = cross recip recip+  (/) = biCross (/) (/)++-- | Tuple instance of `ExpField` typeclass.+instance+  (ExpField a, ExpField b) =>+  ExpField (a, b)+  where+  exp = bimap exp exp+  log = bimap log log+  (**) = biCross (**) (**)+  logBase = biCross logBase logBase+  sqrt = bimap sqrt sqrt++-- | Tuple instance of `TrigField` typeclass.+instance+  (TrigField a, TrigField b) =>+  TrigField (a, b)+  where+  -- Constants+  pi = (pi, pi)++  -- Basic trig functions+  sin = bimap sin sin+  cos = bimap cos cos+  tan = bimap tan tan++  -- Inverse trig functions+  asin = bimap asin asin+  acos = bimap acos acos+  atan = bimap atan atan+  atan2 = biCross atan2 atan2++  -- Hyperbolic functions+  sinh = bimap sinh sinh+  cosh = bimap cosh cosh+  tanh = bimap tanh tanh++  -- Inverse hyperbolic functions+  asinh = bimap asinh asinh+  acosh = bimap acosh acosh+  atanh = bimap atanh atanh++-- | Triple instance of `Additive`.+instance+  (Additive a0, Additive a1, Additive a2) =>+  Additive (a0, a1, a2)+  where+  zero = (zero, zero, zero)+  (+) = biCross3 (+) (+) (+)++-- | Triple instance of `Subtractive`.+instance+  (Subtractive a0, Subtractive a1, Subtractive a2) =>+  Subtractive (a0, a1, a2)+  where+  negate (x0, x1, x2) = (negate x0, negate x1, negate x2)+  (-) = biCross3 (-) (-) (-)++-- | Triple instance of `Multiplicative` typeclass.+instance+  (Multiplicative a0, Multiplicative a1, Multiplicative a2) =>+  Multiplicative (a0, a1, a2)+  where+  one = (one, one, one)+  (*) = biCross3 (*) (*) (*)++-- | Triple instance of `Divisive` typeclass.+instance+  (Divisive a0, Divisive a1, Divisive a2) =>+  Divisive (a0, a1, a2)+  where+  recip = cross3 recip recip recip+  (/) = biCross3 (/) (/) (/)++-- | Triple instance of `ExpField`.+instance+  (ExpField a0, ExpField a1, ExpField a2) =>+  ExpField (a0, a1, a2)+  where+  exp = cross3 exp exp exp+  log = cross3 log log log+  (**) = biCross3 (**) (**) (**)+  logBase = biCross3 logBase logBase logBase+  sqrt = cross3 sqrt sqrt sqrt++-- | Triple instance of `TrigField`.+instance+  (TrigField a, TrigField b, TrigField c) =>+  TrigField (a, b, c)+  where+  -- Constants+  pi = (pi, pi, pi)++  -- Basic trig functions+  sin = cross3 sin sin sin+  cos = cross3 cos cos cos+  tan = cross3 tan tan tan++  -- Inverse trig functions+  asin = cross3 asin asin asin+  acos = cross3 acos acos acos+  atan = cross3 atan atan atan+  atan2 = biCross3 atan2 atan2 atan2++  -- Hyperbolic functions+  sinh = cross3 sinh sinh sinh+  cosh = cross3 cosh cosh cosh+  tanh = cross3 tanh tanh tanh++  -- Inverse hyperbolic functions+  asinh = cross3 asinh asinh asinh+  acosh = cross3 acosh acosh acosh+  atanh = cross3 atanh atanh atanh++-- | Sized Vector instance of `Additive` typeclass.+instance+  (KnownNat n, Additive a, DVG.Vector v a) =>+  Additive (DVGS.Vector v n a)+  where+  zero = DVGS.replicate zero+  (+) = DVGS.zipWith (+)++-- | Sized Vector instance of `Subtractive` typeclass.+instance+  (KnownNat n, Subtractive a, DVG.Vector v a) =>+  Subtractive (DVGS.Vector v n a)+  where+  negate = DVGS.map zero+  (-) = DVGS.zipWith (-)++-- | Sized Vector instance of `Multiplicative` typeclass.+instance+  (KnownNat n, Multiplicative a, DVG.Vector v a) =>+  Multiplicative (DVGS.Vector v n a)+  where+  one = DVGS.replicate one+  (*) = DVGS.zipWith (*)++-- | Sized Vector instance of `Divisive` typeclass.+instance+  (KnownNat n, Divisive a, DVG.Vector v a) =>+  Divisive (DVGS.Vector v n a)+  where+  (/) = DVGS.zipWith (/)++-- | Sized Vector instance of `ExpField` typeclass.+instance+  (KnownNat n, ExpField a, DVG.Vector v a) =>+  ExpField (DVGS.Vector v n a)+  where+  exp = DVGS.map exp+  log = DVGS.map log+  (**) = DVGS.zipWith (**)+  logBase = DVGS.zipWith logBase+  sqrt = DVGS.map sqrt++-- | Sized Vector instance of `TrigField` typeclass.+instance+  (KnownNat n, TrigField a, DVG.Vector v a) =>+  TrigField (DVGS.Vector v n a)+  where+  -- Constants+  pi = DVGS.replicate pi++  -- Basic trig functions+  sin = DVGS.map sin+  cos = DVGS.map cos+  tan = DVGS.map tan++  -- Inverse trig functions+  asin = DVGS.map asin+  acos = DVGS.map acos+  atan = DVGS.map atan+  atan2 = DVGS.zipWith atan2++  -- Hyperbolic functions+  sinh = DVGS.map sinh+  cosh = DVGS.map cosh+  tanh = DVGS.map tanh++  -- Inverse hyperbolic functions+  asinh = DVGS.map asinh+  acosh = DVGS.map acosh+  atanh = DVGS.map atanh++-- | `Data.Stream.Stream` instances  of `Additive` typeclass.+instance+  (Additive a) =>+  Additive (DS.Stream a)+  where+  zero = DS.repeat zero+  (+) = DS.zipWith (+)++-- | `Data.Stream.Stream` instances  of `Subtractive` typeclass.+instance+  (Subtractive a) =>+  Subtractive (DS.Stream a)+  where+  negate = fmap negate+  (-) = DS.zipWith (-)++-- | `Data.Stream.Stream` instances  of `Multiplicative` typeclass.+instance+  (Multiplicative a) =>+  Multiplicative (DS.Stream a)+  where+  one = DS.repeat one+  (*) = liftA2 (*)++-- | `Data.Stream.Stream` instances  of `Divisive` typeclass.+instance+  (Divisive a) =>+  Divisive (DS.Stream a)+  where+  recip = fmap recip+  (/) = liftA2 (/)++-- | `Data.Stream.Stream` instances  of `ExpField` typeclass.+instance+  (ExpField a) =>+  ExpField (DS.Stream a)+  where+  exp = fmap exp+  log = fmap log+  (**) = liftA2 (**)+  logBase = liftA2 logBase+  sqrt = fmap sqrt++-- | `Data.Stream.Stream` instances  of `TrigField` typeclass.+instance+  (TrigField a) =>+  TrigField (DS.Stream a)+  where+  -- Constants+  pi = DS.repeat pi++  -- Basic trig functions+  sin = fmap sin+  cos = fmap cos+  tan = fmap tan++  -- Inverse trig functions+  asin = fmap asin+  acos = fmap acos+  atan = fmap atan+  atan2 = liftA2 atan2++  -- Hyperbolic functions+  sinh = fmap sinh+  cosh = fmap cosh+  tanh = fmap tanh++  -- Inverse hyperbolic functions+  asinh = fmap asinh+  acosh = fmap acosh+  atanh = fmap atanh++-- | `Maybe` instance of `Additive`.+instance+  (Additive a) =>+  Additive (Maybe a)+  where+  zero = Just zero+  (+) = liftA2 (+)++-- | `Maybe` instance of `Subtractive`.+instance+  (Subtractive a) =>+  Subtractive (Maybe a)+  where+  negate = fmap negate+  (-) = liftA2 (-)++-- | `Maybe` instance of `Multiplicative`.+instance+  (Multiplicative a) =>+  Multiplicative (Maybe a)+  where+  one = Just one+  (*) = liftA2 (*)++-- | `Maybe` instance of `Divisive`.+instance+  (Divisive a) =>+  Divisive (Maybe a)+  where+  recip = fmap recip+  (/) = liftA2 (/)++-- | `Maybe` instance of `ExpField`.+instance+  (ExpField a) =>+  ExpField (Maybe a)+  where+  exp = fmap exp+  log = fmap log+  (**) = liftA2 (**)+  logBase = liftA2 logBase+  sqrt = fmap sqrt++-- | `Maybe` instance of `TrigField`.+instance+  (TrigField a) =>+  TrigField (Maybe a)+  where+  -- Constants+  pi = Just pi++  -- Basic trig functions+  sin = fmap sin+  cos = fmap cos+  tan = fmap tan++  -- Inverse trig functions+  asin = fmap asin+  acos = fmap acos+  atan = fmap atan+  atan2 = liftA2 atan2++  -- Hyperbolic functions+  sinh = fmap sinh+  cosh = fmap cosh+  tanh = fmap tanh++  -- Inverse hyperbolic functions+  asinh = fmap asinh+  acosh = fmap acosh+  atanh = fmap atanh
+ src/Numeric/InfBackprop/Tutorial.hs view
@@ -0,0 +1,2163 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS -Wno-unused-imports #-}+{-# OPTIONS_HADDOCK show-extensions #-}++-- |+-- Module    :  Numeric.InfBackprop.Tutorial+-- Copyright   :  (C) 2023-2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Tutorial for the+-- [inf-backprop](https://hackage.haskell.org/package/inf-backprop) package.+module Numeric.InfBackprop.Tutorial+  ( -- * Quick Start++    -- ** Basic Examples #quick-start-simple-derivative#+    -- $quick-start-simple-derivative++    -- ** Derivatives for Symbolic Expressions #quick-start-derivatives-for-symbolic-expressions#+    -- $quick-start-derivatives-for-symbolic-expressions++    -- ** Symbolic Expressions Visualization #squick-start-ymbolic-expressions-visualization#+    -- $quick-start-symbolic-expressions-visualization++    -- ** Gradient over a Two-Argument Function #quick-start-function-of-two-argument-functions#+    -- $quick-start-gradient-of-two-argument-functions++    -- ** Siskind-Pearlmutter Example #quick-start-siskind-pearlmutter-example#+    -- $quick-start-siskind-pearlmutter-example++    -- * How it Works+    -- $how-it-works++    -- ** The Backpropagation Derivative #how-it-works-backpropagation#+    -- $how-it-works-backpropagation++    -- ** Core Type: `RevDiff` #how-it-works-core-type-RevDiff#+    -- $how-it-works-core-type-RevDiff++    -- ** Functions Overloading #how-it-works-functions-overloading#+    -- $how-it-works-functions-overloading++    -- ** Tangent and Cotangent Spaces #how-it-works-tangent-space#+    -- $how-it-works-tangent-space++    -- * Differentiation for Structured Types #differentiation-for-structured-types#+    -- $differentiation-for-structured-types++    -- ** Structured Value Type #differentiation-for-structured-types-structured-value#+    -- $differentiation-for-structured-types-structured-value++    -- *** Basic Examples: Structured Value Types #differentiation-for-structured-types-structured-value-basic-examples#+    -- $differentiation-for-structured-types-structured-value-basic-examples++    -- *** Custom Derivative: Structured Value Types #differentiation-for-structured-types-structured-value-custom-derivative#+    -- $differentiation-for-structured-types-structured-value-custom-derivative++    -- *** How it Works: Structured Value Types #differentiation-for-structured-types-structured-value-how-it-works#+    -- $differentiation-for-structured-types-structured-value-how-it-works++    -- *** Defining Custom Value Type #differentiation-for-structured-types-structured-value-defining-custom-value-type#+    -- $differentiation-for-structured-types-structured-value-defining-custom-value-type++    -- ** Structured Argument Type #differentiation-for-structured-types-structured-argument-type#+    -- $differentiation-for-structured-types-structured-argument-type++    -- *** Basic Examples: Structured Argument Types #differentiation-for-structured-types-structured-argument-type-basic-examples#+    -- $differentiation-for-structured-types-structured-argument-type-basic-examples++    -- *** Custom Derivative: Structured Argument Types #differentiation-for-structured-types-structured-argument-type-custom-gradient#+    -- $differentiation-for-structured-types-structured-argument-type-custom-gradient++    -- *** How it Works: Structered Argument Types #differentiation-for-structured-types-structured-argument-type-how-it-works#+    -- $differentiation-for-structured-types-structured-argument-type-how-it-works++    -- *** Defining Custom Argument Type #differentiation-for-structured-types-structured-argument-type-defining-custom-type#+    -- $differentiation-for-structured-types-structured-argument-type-defining-custom-type++    -- * Performance Remarks #performance-remarks#+    -- $performance-remarks++    -- ** Subexpression Elimination #sperformance-remarks-ubexpression-elimination#+    -- $performance-remarks-subexpression-elimination++    -- ** Forward Step Results Reusage #forward-step-results-reusage#+    -- $performance-remarks-forward-step-results-reusage++    -- * What is Next #what-is-next#+    -- $what-is-next+  )+where++import Control.Category ((>>>))+import Control.Lens (set, view)+import Data.FiniteSupportStream (FiniteSupportStream (toVector), head, singleton)+import qualified Data.List as DL+import Data.Proxy (Proxy (Proxy))+import Data.Stream (Stream, fromList, head, take)+import qualified Data.Stream as DS+import qualified Data.Stream as Data+import Data.Tuple (fst, snd, uncurry)+import Data.Type.Equality (type (~))+import qualified Data.Vector as DV+import qualified Data.Vector.Fixed as DVF+import Data.Vector.Generic.Sized (Vector, foldl')+import qualified Data.Vector.Generic.Sized as DVGS+import Debug.DiffExpr+  ( BinarySymbolicFunc,+    SymbolicFunc,+    TSE,+    TracedSimpleExpr,+    binarySymbolicFunc,+    unarySymbolicFunc,+  )+import Debug.SimpleExpr (SE, SimpleExpr, number, simplify, simplifyExpr, variable)+import Debug.SimpleExpr.Utils.Traced (Traced (MkTraced), addTraceUnary)+import Debug.Trace (trace)+import GHC.Base (Float, Int, const, fmap, foldr, id, undefined, ($), (.), (<>))+import GHC.Integer (Integer)+import GHC.Natural (Natural, minusNatural)+import GHC.Show (Show (show))+import GHC.TypeNats (KnownNat)+import NumHask+  ( Additive,+    Distributive,+    Divisive,+    ExpField,+    FromInteger (fromInteger),+    Multiplicative,+    Ring,+    Subtractive,+    TrigField,+    cos,+    cosh,+    exp,+    log,+    negate,+    one,+    sin,+    sinh,+    zero,+    (*),+    (+),+    (-),+    (/),+  )+import qualified NumHask as NH+import Numeric.InfBackprop+  ( CT,+    Cotangent,+    Dual,+    RevDiff (MkRevDiff),+    RevDiff',+    Tangent,+    autoArg,+    autoVal,+    backprop,+    boxedVectorArg,+    boxedVectorArgDerivative,+    boxedVectorVal,+    constDiff,+    customArgDerivative,+    customArgValDerivative,+    fromProfunctors,+    fromVanLaarhoven,+    initDiff,+    mkBoxedVectorArg,+    mkBoxedVectorVal,+    mkStreamArg,+    mkStreamVal,+    mkTupleArg,+    mkTupleVal,+    scalarArg,+    scalarArgDerivative,+    scalarVal,+    scalarValDerivative,+    simpleDerivative,+    simpleDifferentiableFunc,+    simpleValueAndDerivative,+    stopDiff,+    streamArg,+    streamArgDerivative,+    toProfunctors,+    toVanLaarhoven,+    tupleArg,+    tupleArgDerivative,+    tupleVal,+    twoArgsDerivative,+    twoArgsDerivativeOverY,+    value,+  )+import Numeric.InfBackprop.Instances.NumHask ()+import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+import Numeric.InfBackprop.Utils.Tuple (cross)++-- $quick-start-simple-derivative+--+-- >>> import GHC.Base (Float, fmap, ($))+--+-- In this section, we'll explore how automatic differentiation transforms ordinary+-- mathematical functions into their derivatives, handling everything from basic+-- polynomials to complex compositions without requiring manual derivation.+--+-- We'll start by exploring automatic differentiation+-- through the familiar square function:+--+-- \[+--   f(x) := x^2+-- \]+--+-- To work with our automatic differentiation system, we need operations that can+-- handle not just numbers, but also the dual numbers that carry derivative information.+-- The polymorphic multiplication operator from+-- [numhask](https://hackage.haskell.org/package/numhask)+-- provides this flexibility:+--+-- >>> import NumHask (Multiplicative, (*), (+), log)+--+-- The operator `(*)` has the following type signature:+--+-- > (*) :: Multiplicative a => a -> a -> a+--+-- This polymorphic operator allows us to write functions+-- that work seamlessly with both regular+-- numbers and the extended number types used in automatic differentiation.+--+-- Let's define our square function and see it in action with regular `Float` values:+--+-- >>> f x = x * x+-- >>> fmap f [-3, -2, -1, 0, 1, 2, 3] :: [Float]+-- [9.0,4.0,1.0,0.0,1.0,4.0,9.0]+--+-- Now comes the remarkable part: computing the derivative automatically. The+-- `simpleDerivative` function applies the chain rule automatically, transforming+-- any function built from differentiable primitives into its derivative function.+--+-- We know from calculus that the derivative of \(x^2\) should be:+--+-- \[+--   f'(x) = 2 \cdot x+-- \]+--+-- Let's verify this using automatic differentiation:+--+-- >>> import Numeric.InfBackprop (simpleDerivative)+--+-- >>> f' = simpleDerivative f :: Float -> Float+-- >>> fmap f' [-3, -2, -1, 0, 1, 2, 3]+-- [-6.0,-4.0,-2.0,0.0,2.0,4.0,6.0]+--+-- Notice how each result equals \(2x\), perfectly confirming our analytical derivative+-- \(f'(x) = 2x\). The values \(-6, -4, -2, 0, 2, 4, 6\) correspond exactly to \(2\) times+-- each input value.+--+-- You must provide a type annotation (such as @Float -> Float@) for the derivative+-- function. This ensures correct type inference by the compiler and specifies which+-- numeric type you want to work with.+--+-- Computing higher-order derivatives follows the same pattern. Since composing+-- `simpleDerivative` twice gives us the second derivative, this demonstrates how+-- automatic differentiation naturally handles higher-order derivatives through+-- function composition.+--+-- For our square function, the second derivative should be the constant \(2\):+--+-- \[+--   f''(x) = 2+-- \]+--+-- >>> f'' = simpleDerivative $ simpleDerivative f :: Float -> Float+-- >>> fmap f'' [-3, -2, -1, 0, 1, 2, 3]+-- [2.0,2.0,2.0,2.0,2.0,2.0,2.0]+--+-- Perfect! The constant value @2.0@ across all inputs confirms that our second+-- derivative is indeed the constant function \(f''(x) = 2\).+--+-- This approach scales naturally to arbitrarily complex functions. Let's explore+-- how automatic differentiation handles function composition by examining a more+-- intricate example involving logarithms and polynomial terms:+--+-- \[+--   g(x) := \log (x^2 + x^3)+-- \]+--+-- We'll use integer powers from the+-- 'Numeric.InfBackprop.Algebra.IntegralPower'+-- module:+--+-- >>> import Debug.SimpleExpr.Utils.Algebra ((^))+--+-- >>> g x = log (x ^ 2 + x ^ 3)+-- >>> g' = simpleDerivative g :: Float -> Float+-- >>> g 1 :: Float+-- 0.6931472+-- >>> g' 1 :: Float+-- 2.5+--+-- We can verify this result analytically. The derivative of \(\log(x^2 + x^3)\) using+-- the chain rule is:+--+-- \[+--   g'(x) = \frac{d}{dx}[\log(x^2 + x^3)] = \frac{1}{x^2 + x^3} \cdot \frac{d}{dx}[x^2 + x^3] = \frac{2x + 3x^2}{x^2 + x^3}+-- \]+--+-- At \(x = 1\):+--+-- \[+-- g'(1) = \frac{2 \cdot 1 + 3 \cdot 1^2}{1^2 + 1^3} = \frac{2 + 3}{1 + 1} = \frac{5}{2} = 2.5+-- \]+--+-- The automatic differentiation result matches our analytical calculation perfectly,+-- demonstrating how the system correctly applies the chain rule even for complex+-- composite functions.++-- $quick-start-derivatives-for-symbolic-expressions+--+-- >>> import NumHask ((*), sin, cos)+-- >>> import Debug.SimpleExpr (variable, simplify, SimpleExpr, SE)+-- >>> import Numeric.InfBackprop (simpleDerivative)+--+-- In many cases, it is more convenient to illustrate differentiation using+-- symbolic expressions rather than concrete numeric values.+-- Unlike numeric differentiation, symbolic expressions allow us to+-- inspect, transform, and optimize derivatives algebraically.+--+-- We use the+-- [simple-expr](https://hackage.haskell.org/package/simple-expr)+-- package to construct and manipulate symbolic expressions.+--+-- For example, consider the function:+--+-- \[+--   f(x) := \sin(x^2)+-- \]+--+-- We can define it symbolically as follows:+--+-- >>> import Debug.SimpleExpr.Utils.Algebra (AlgebraicPower, (^))+--+-- >>> x = variable "x" :: SimpleExpr+-- >>> f x = sin (x ^ 2)+-- >>> f x :: SimpleExpr+-- sin(x^2)+--+-- where 'SimpleExpr' is a symbolic expression type from+-- [simple-expr](https://hackage.haskell.org/package/simple-expr)+--+-- Computing the symbolic derivative+--+-- \[+--   f'(x) := 2x \cdot \cos(x^2)+-- \]+--+-- is equally straightforward:+--+-- >>> f' = simpleDerivative f+-- >>> simplify $ f' x :: SimpleExpr+-- (2*x)*cos(x^2)+--+-- The `simplify` function from+-- [simple-expr](https://hackage.haskell.org/package/simple-expr)+-- reduces redundant expressions like+-- @*1@ and @+0@.+-- and presents the result in a more readable algebraic form.+--+-- Bellow, we will use the @SE@ type synonym for @SimpleExpr@.+--+-- Note that we continue to use generic definitions of functions like 'cos',+-- as well as operators such as '(*)', from the+-- [numhask](https://hackage.haskell.org/package/numhask)+-- package.++-- $quick-start-symbolic-expressions-visualization+--+-- The+-- [simple-expr](https://hackage.haskell.org/package/simple-expr)+-- package includes visualization tools that help illustrate the process of symbolic+-- differentiation.+--+-- >>> import Debug.SimpleExpr (SimpleExpr, variable, simplify, plotExpr, plotDGraphPng)+-- >>> import Debug.DiffExpr (unarySymbolicFunc)+-- >>> import Numeric.InfBackprop (simpleDerivative)+--+-- As a warm-up, consider a simple composition of two symbolic functions:+--+-- \[+--   x \mapsto g(f(x))+-- \]+--+-- This can be represented as:+--+-- >>> x = variable "x" :: SimpleExpr+-- >>> f = unarySymbolicFunc "f" :: SimpleExpr -> SimpleExpr+-- >>> g = unarySymbolicFunc "g" :: SimpleExpr -> SimpleExpr+-- >>> g (f x) :: SimpleExpr+-- g(f(x))+--+-- You can visualize this expression using:+--+-- > plotExpr $ g (f x)+--+-- ![Function composition](doc/images/composition.png)+--+-- To visualize the first derivative of this composition, use:+--+-- > plotExpr $ simplify $ simpleDerivative (g . f) x+--+-- ![First derivative](doc/images/composition_derivative.png)+--+-- Visualizing the second derivative is just as easy:+--+-- > plotExpr $ simplify $ simpleDerivative (simpleDerivative (g . f)) x+--+-- ![Second derivative](doc/images/composition_second_derivative.png)++-- $quick-start-gradient-of-two-argument-functions+--+-- In this section, we focus on computing partial derivatives of functions+-- with two arguments.+--+-- As a starting point, consider a symbolic function @h@ that takes two arguments.+-- (See+-- [Derivatives for Symbolic Expressions](#g:quick-45-start-45-derivatives-45-for-45-symbolic-45-expressions)+-- .)+--+-- >>> x = variable "x"+-- >>> y = variable "y"+-- >>> h = binarySymbolicFunc "h" :: BinarySymbolicFunc a => a -> a -> a+-- >>> h x y+-- h(x,y)+--+-- To compute partial derivatives, we use the `twoArgsDerivative` operator,+-- which has a somewhat advanced type signature (see Section ??? for details).+-- In practice, its usage is straightforward:+--+-- >>> :{+--    h' :: SE -> SE -> (SE, SE)+--    h' x y = simplify $ twoArgsDerivative h x y+-- :}+--+-- This returns a pair of partial derivatives:+--+-- >>> h' x y+-- (h'_1(x,y),h'_2(x,y))+--+-- We can also compute the second-order derivatives by nesting `twoArgsDerivative`:+--+-- >>> :{+--    h'' :: SE -> SE -> ((SE, SE), (SE, SE))+--    h'' x y = simplify $ twoArgsDerivative (twoArgsDerivative h) x y+-- :}+--+-- >>> h'' x y+-- ((h'_1'_1(x,y),h'_1'_2(x,y)),(h'_2'_1(x,y),h'_2'_2(x,y)))+--+-- In this example, @h\'_1\'_2@ refers to the second partial derivative of @h@+-- with respect to @x@ and then @y@, and so on.+--+-- Note that `twoArgsDerivative` is polymorphic over the return type of the function,+-- but it works only for functions that take exactly /two arguments/.+--+-- In contrast, the @customArgValDerivative autoArg@ operator+-- (see+-- [Structured Argument Type](#g:differentiation-45-for-45-structured-45-types-45-structured-45-argument-45-type))+-- can handle functions of arbitrary arity, but it is /not/ polymorphic+-- over the return type of the function.++-- $quick-start-siskind-pearlmutter-example+--+-- We are now ready to revisit a classic example of higher-order automatic differentiation+-- from the paper by Siskind and Pearlmutter:+-- [Siskind & Pearlmutter (2005), "Perturbation Confusion and Referential Transparency"](https://engineering.purdue.edu/~qobi/papers/ifl2005.pdf)+-- The expression of interest is:+--+-- \[+--    \left.+--      \frac{\partial}{\partial x}+--      \left(+--        x+--          \left(+--            \left.+--              \frac{\partial}{\partial y}+--              \left(+--                x + y+--              \right)+--            \right|_{y=1}+--          \right)+--      \right)+--    \right|_{x=1}+--    = 1+-- \]+--+-- To implement this, we begin by applying the partial derivative operator+-- `twoArgsDerivativeOverY`, which differentiates a binary function+-- with respect to its /second/ argument:+--+-- For example, to compute+--+-- \[+--    \frac{\partial}{\partial y}+--    (x \cdot y)+--    = x+-- \]+--+-- we write:+--+-- >>> x = variable "x"+-- >>> y = variable "y"+-- >>> simplify $ twoArgsDerivativeOverY (*) x y :: SE+-- x+--+-- To evaluate this derivative at @y = 1@, we can use the `stopDiff` function,+-- which performs symbolic substitution. For instance,+--+-- > stopDiff $ number 1+--+-- effectively replaces @y@ with @1@ in the expression.+--+-- So the expression+--+-- \[+--    \left.+--      \frac{\partial}{\partial y}+--      (x \cdot y)+--    \right|_{y=1}+--    = x+-- \]+--+-- is implemented as:+--+-- >>> simplify $ twoArgsDerivativeOverY (*) x 1 :: SE+-- x+--+-- Now we can wrap the entire expression in a derivative with respect to @x@:+--+-- \[+--    \frac{d}{dx}+--    \left.+--      \frac{\partial}{\partial y}+--      (x \cdot y)+--    \right|_{y=1}+--    = 1+-- \]+--+-- This becomes:+--+-- >>> :{+--    simplify $+--      (simpleDerivative $ \x_ -> twoArgsDerivativeOverY (*) x_ 1) x :: SE+-- :}+-- 1+--+-- The same logic works not just for symbolic expressions (`SE`),+-- but also for concrete numeric types such as `Float`:+--+-- >>> :{+--    simpleDerivative+--      (\x -> x * twoArgsDerivativeOverY (+) x 1)+--      (2024 :: Float)+-- :}+-- 1.0+--+-- Note: when working with numeric types like `Float`,+-- the variable @x@ must be assigned a concrete `Float` value.++-- $how-it-works-backpropagation+--+-- To clarify the concept of backpropagation, consider the following example.+--+-- Let @h@, @f@, and @g@ be three simple functions of type:+--+-- \[+--   \mathbb{R} \rightarrow \mathbb{R}+-- \]+--+-- Now consider their composition:+--+-- \[+--   x \mapsto g(f(h(x)))+-- \]+--+-- The first derivative of this composition, using the chain rule, is:+--+-- \[+--   x \mapsto h'(x) \cdot f'(h(x)) \cdot g'(f(h(x)))+-- \]+--+-- This composition and its derivative can be illustrated+-- using the following computation graph:+--+-- ![Backpropagation diagram](doc/images/backprop.drawio.png)+--+-- The top path (from left to right) represents the /forward pass/,+-- where values are computed through the function chain.+-- The bottom path (from right to left) represents the /backward pass/,+-- where derivatives are propagated.+--+-- According to the backpropagation strategy,+-- the derivative is computed in reverse order, as follows:+--+-- 1. Evaluate @h(x)@.+--+-- 2. Compute @f(h(x))@.+--+-- 3. Compute @g(f(h(x)))@.+--+-- 4. Compute the top derivative: @g'(f(h(x)))@.+--+-- 5. Compute the next derivative: @f'(h(x))@.+--+-- 6. Multiply: @g'(f(h(x))) * f'(h(x))@.+--+-- 7. Compute the base derivative: @h'(x)@.+--+-- 8. Multiply the result from step 6 by @h'(x)@.+--+-- The product of these three derivatives gives the full derivative of the composition.+--+-- Note: While it is possible to compute this derivative in forward order+-- (i.e., from left to right) or+-- any other order,+-- the backpropagation strategy is more efficient+-- for deep machine learning applications.+-- Forward-mode differentiation is beyond the scope of this library.+--+-- Generalizing this approach to longer function chains or functions from and to vector spaces+-- is straightforward and follows the same principles.++-- $how-it-works-core-type-RevDiff+--+-- All the derivative computations from the previous example —+-- specifically for the function @f@ —+-- can be conceptually divided into two phases:+--+-- 1. /Forward step/: Compute the value @f(h(x))@.+--+-- 2. /Backward step/:+-- Compute the derivative @f'(h(x))@, and multiply it by the previously+-- obtained derivative @g'(f(h(x)))@.+--+-- Note that the value @h(x)@ is used in both the forward and backward steps.+--+-- The corresponding diagram can be visualized as:+--+-- ![Backpropagation lens diagram](doc/images/lens.drawio.png)+--+-- A differentiable function from type @a@ to type @b@ can be represented+-- as a pair of functions:+-- a /forward/ function and a /backward/ (derivative propagation) function:+--+-- @+-- newtype DifferentiableFunc a b = MkDifferentiableFunc {+--     forward  :: a -> b,+--     backward :: a -> CT b -> CT a+--   }+-- @+--+-- The meaning of the `CT` type family (short for /cotangent/)+-- will be discussed in the+-- [next section](#g:how-45-it-45-works-45-tangent-45-space).+-- For now, you may assume @CT a ~ a@.+--+-- From a categorical perspective, a @DifferentiableFunc@ behaves like a lens:+--+-- > DifferentiableFunc a b ≈ Lens a (CT a) b (CT b)+--+-- where @forward@ corresponds to `view`, and @backward@ corresponds to `set`.+--+-- In principle, one could define a category of differentiable functions using lenses,+-- replacing standard function composition `(.)` with lens composition `(% or >>>)`.+-- However, this comes at a cost: we lose the ability to use familiar syntax such as+-- function application @y = f x@.+--+-- To preserve the familiar function syntax — e.g., keeping definitions like+-- @sin :: a -> a@+-- and supporting ordinary function application — we follow an approach inspired by the+-- [ad](https://hackage.haskell.org/package/ad)+-- and+-- [backprop](https://hackage.haskell.org/package/backprop) libraries.+-- See also, for example,+-- [this article](https://arxiv.org/pdf/1804.00746)+--+-- Fixing a type @t@ (which plays the role of the final output), we can reinterpret+-- a lens-like function+--+-- > dFunc :: DifferentiableFunc a b+--+-- as a transformation on differentiable values:+--+-- > lensToMap :: DifferentiableFunc a b -> DifferentiableFunc t a -> DifferentiableFunc t b+-- > lensToMap dFunc = dFunc <<<      -- lens composition+--+-- So, @lensToMap dFunc@ becomes a plain Haskell function:+--+-- > DifferentiableFunc t a -> DifferentiableFunc t b+--+-- Mathematically, this is a /hom-functors/ from+-- the cathegory of law-breaking lenses.+--+-- Next, note that the type+--+-- > DifferentiableFunc t a+--+-- is isomorphic to:+--+-- > t -> (a, CT a -> CT t)+--+-- But the actual value of type @t@ is not used the composion with+-- @DifferentiableFunc a b@.+-- Therefore, we can drop the @t@ parameter and reduce the transformation:+--+-- > DifferentiableFunc t a -> DifferentiableFunc t b+--+-- to a plain function:+--+-- > (a, CT a -> CT t) -> (b, CT b -> CT t)+--+-- This motivates the definition of the core type:+--+-- @+-- data RevDiff' t a = MkRevDiff+--   { value    :: a+--   , backprop :: CT a -> CT t+--   }+-- @+--+-- For example, suppose we have a function:+--+-- > f  :: Float -> Float    -- function f+-- > f' :: Float -> Float    -- derivative of f+--+-- Then the differentiable version of @f@ can be defined as:+--+-- @+-- differentiableF :: RevDiff' t Float -> RevDiff' t Float+--   differentiableF (MkRevDiff x backprop) =+--   MkRevDiff (f x) (\cx -> backprop ((f' x) * cx))+-- @+--+-- To evaluate the function at a point @x@:+--+-- > y = value $ differentiableF (MkRevDiff x id)+--+-- To evaluate its derivative at @x@:+--+-- > y' = backprop (differentiableF (MkRevDiff x id)) 1.0+--+-- Here, the transition from type @a@ to @RevDiff' t a@ carries two parts:+--+-- - `value`: the forward-pass result+--+-- - `backprop`: a stack of backward-pass derivative transformations+--+-- from type @CT a@ to @CT t@.+--+-- In the example above, the value:+--+-- > MkRevDiff x id :: RevDiff Float Float+--+-- represents the /initial value/ of the backpropagation stack.+-- Applying @differentiableF@+-- results in:+--+-- > MkRevDiff (f x) (\cx -> id ((f' x) * cx)) = MkRevDiff (f x) ((f' x) *)+--+-- So applying `backprop` to @1.0 :: @`Float` gives us the derivative value @f' x@.+--+-- For convenience and flexibility, this package defines a three-parameter type:+-- @+-- data RevDiff a b c = MkRevDiff {value :: c, backprop :: b -> a}+-- @+--+-- This generalized structure allows us to separate the types involved in the+-- forward pass (the value of type @c@) from those used in the backward pass+-- (the gradient computation from @b@ to @a@).+--+-- We also provide a specialized type alias for common use cases:+--+-- > type RevDiff' a b = RevDiff (CT a) (CT b) b+--+-- This three-parameter design enables powerful abstraction capabilities.+-- In particular, it allows us to implement both profunctor and Van Laarhoven+-- representations for differentiable functions, providing multiple ways to+-- compose and manipulate automatic differentiation computations.+--+-- These alternative representations can be accessed through the conversion+-- functions `fromProfunctors`, `toProfunctors`, `fromVanLaarhoven`, and+-- `toVanLaarhoven`, each offering different compositional properties suited+-- to various use cases.+--+-- Generalizing this to arbitrary compositions of differentiable functions+-- is straightforward+-- and follows the same backpropagation principle.++-- $how-it-works-functions-overloading+--+-- Our goal now is to make functions such as @sin@ and @(*)@ differentiable,+-- while still being able to use them as ordinary functions — in particular,+-- to apply them to arguments and compose them using '(.)'.+--+-- To this end, we follow the approach used in the+-- [numhask](https://hackage.haskell.org/package/numhask) package.+-- In this package, functions like `sin` and `(*)` are defined as polymorphic methods+-- of typeclasses.+--+-- For instance, the function `sin` is a method of the typeclass:+--+-- @+-- class TrigField a where+--   ...+--   sin :: a -> a+-- @+--+-- Similarly, multiplication is defined via:+--+-- @+-- class Multiplicative a where+--   ...+--   (*) :: a -> a -> a+-- @+--+-- These typeclasses have instances, for example, for the type `Float`.+-- Instancies for `SE` are provided in+-- [simple-expr](https://hackage.haskell.org/package/simple-expr)+-- package.+--+-- To make `sin` and `(*)` differentiable in the backpropagation framework,+-- it is enough to define instances for:+--+-- > RevDiff Float Float+--+-- These instances can be implemented as follows.+-- (The type family 'CT' can be ignored for now, we may assume @CT a ~ a@ for simplicity.)+--+-- @+-- instance Additive (CT t) => TrigField (RevDiff t Float) where+--   ...+--   sin :: RevDiff t Float -> RevDiff t Float+--   sin MkRevDiff {value = x, backprop = backpropX} = MkRevDiff {+--       value    = sin x,+--       backprop = backpropX . ((cos x) *)+--     }+-- @+--+-- @+-- instance Additive (CT t) => Multiplicative (RevDiff t Float) where+--   ...+--   (*) :: RevDiff t Float -> RevDiff t Float -> RevDiff t Float+--   MkRevDiff x backpropX * MkRevDiff y backpropY =+--     MkRevDiff {+--         value    = x * y,+--         backprop = backpropX . (y *) + backpropY . (x *)+--       }+-- @+--+-- To compute /second derivatives/, we can use a nested type like:+--+-- > RevDiff (RevDiff Float Float) (RevDiff Float Float)+--+-- That is, the outer layer performs backpropagation through the inner derivative.+-- Similarly, higher-order derivatives can be obtained by nesting @RevDiff@ types further.+--+-- These instances can also be generalized to any numeric type @a@, not just `Float`,+-- allowing us to define /infinitely differentiable/ functions.++-- $how-it-works-tangent-space+--+-- In this section, we explain the purpose of the type family `CT` and how it is used.+-- In most practical cases, we can assume @CT a ~ a@ and safely ignore it.+--+-- One of the challenges in automatic differentiation is that+-- the value type of a function and the value type of its derivative+-- may not coincide, even when the input is scalar (for example, a real number).+-- From a mathematical perspective, this corresponds to the need to work with+-- tangent and cotangent bundles.+--+-- For instance, if a scalar-valued function takes a vector as input,+-- its derivative is also vector-valued.+-- However, this correspondence does not hold in general.+--+-- Consider the case where the input is an infinite sequence+-- (such as an infinte list or stream).+-- The derivative of a function on such inputs is a finite-length sequence+-- (a sparse or finite-support vector; see the `FiniteSupportStream` type).+-- Conversely, a function on finite-support streams has a derivative+-- that is generally represented as an infinite stream.+--+-- This distinction arises because the convolution of two infinite streams+-- is not defined in general.+-- On the other hand, every linear functional on streams can be represented+-- as a convolution with a finite-length vector.+-- Conversely, a convolution with a finite-length vector defines+-- a linear functional on infinite streams.+--+-- Similarly, any linear functional on all bounded finite-length vectors+-- can be represented as a convolution with an infinite sequence.+-- And conversely, convolution with an infinite sequence yields+-- a linear functional on finite-length vectors.+--+-- These distinctions are not just mathematical formalisms,+-- but real practical constraints.+-- In particular, the convolution of two streams cannot be calculated.+-- In this package, the Haskell type system cannot safely express, for example,+-- that the derivative of a function over `Stream` should be of type `Stream`,+-- or that the derivative of a function over `FiniteSupportStream`+-- should also be of type `FiniteSupportStream`.+--+-- Another example comes from geometry.+-- Consider a function defined on the surface of a unit sphere in 3D space.+-- In this case, the derivative at each point must lie in the tangent plane+-- to the sphere at that point — not just any 3D vector.+-- Therefore, the derivative type differs from the function's output type.+--+-- More generally, in differential geometry,+-- functions are defined on manifolds,+-- and their derivatives take values in the cotangent bundle of the manifold.+--+-- To model this distinction in Haskell,+-- we introduce the type family `CT`, which stands for "cotangent type".+-- For example:+--+-- > CT Float = Float+--+-- > CT (a, b) = (CT a, CT b)+--+-- > CT (Vector a) = Vector (CT a)+--+-- > CT (Stream a) = FiniteSupportStream (CT a)+--+-- > CT (FiniteSupportStream a) = Stream (CT a)+--+-- > CT (E2NormedVector a) = Vector (CT a)+--+-- The type family `CT` is defined as a composition of two type families:+-- `Tangent` and `Dual`:+--+-- > CT a = Dual (Tangent a)+--+-- The `Tangent` family describes the type of tangent vectors.+-- For example:+--+-- > Tangent Float = Float+--+-- > Tangent (Stream a) = Stream (Tangent a)+--+-- > Tangent (FiniteSupportStream a) = Tangent (FiniteSupportStream a)+--+-- > Tangent (E2NormedVector a) = Vector (Tangent a)+--+-- The `Dual` family encodes the dual space (linear functionals):+--+-- > Dual Float = Float+--+-- > Dual (Stream a) = FiniteSupportStream (Dual a)+--+-- > Dual (FiniteSupportStream a) = Stream (Dual a)+--+-- > Dual (E2NormedVector a) = Undefined+--+-- In order to support differentiation over a new type that is not already+-- handled by this package, one needs to define appropriate instances+-- for both `Tangent` and `Dual` for that type.++-- $differentiation-for-structured-types+--+-- This library supports the differentiation of functions of type+-- @ f :: a -> b @+-- for potentially any types @a@ and @b@.+-- Thus, the derivative operator has the type:+--+-- > (a -> b) -> (a -> c)+--+-- The argument type @a@ is the same for both the original function+-- @f :: a -> b@ and its derivative+-- @f' :: a -> c@.+-- However, the result type @c@ of the derivative+-- depends in a non-trivial way on both @a@ and @b@.+--+-- For example, the derivative of a vector-valued function of a tuple+-- is a vector of tuples:+--+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- @+-- f  :: (Float, Float) -> BoxedVector 3 Float+-- f' :: (Float, Float) -> BoxedVector 3 (Float, Float)+-- @+--+-- To illustrate the approach, consider a representative example:+-- a function from a tuple to a 3D vector.+--+-- >>> :{+--   sphericToVec :: (TrigField a) => (a, a) -> BoxedVector 3 a+--   sphericToVec (theta, phi) =+--     DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta)+-- :}+--+-- We will use the `customArgValDerivative` operator, which takes three arguments:+--+-- 1. The argument structure descriptor — in this case, `tupleArg`,+-- which is used for the @(a, a)@ input.+--+-- 2. The value structure descriptor — in this case, `boxedVectorVal`,+-- used for output type @BoxedVector 3 _@.+--+-- 3. The function to differentiate — in this case, @sphericToVec@.+--+-- The derivative is then defined as:+--+-- >>> import Debug.SimpleExpr.Utils.Algebra (IntegerPower)+-- >>> :{+--   sphericToVec'V1 :: (TrigField a, ExpField a, IntegerPower a, a ~ CT a) =>+--     (a, a) -> BoxedVector 3 (a, a)+--   sphericToVec'V1 = customArgValDerivative tupleArg boxedVectorVal sphericToVec+-- :}+--+-- The type family `CT` and its meaning are explained in section+-- [Tangent and cotangent spaces](#g:how-45-it-45-works-45-tangent-45-space).+-- For now, it can be ignored.+-- The types and definitions of `tupleArg` and `boxedVectorVal`,+-- as well as how to construct them for other types,+-- will be covered in the following sections.+--+-- Alternatively, the argument and value structure can be inferred automatically+-- using `autoArg` and `autoVal`:+--+-- >>> :{+--   sphericToVec'V2 :: (TrigField a, ExpField a, IntegerPower a, a ~ CT a) =>+--     (a, a) -> BoxedVector 3 (a, a)+--   sphericToVec'V2 = customArgValDerivative autoArg boxedVectorVal sphericToVec+-- :}+--+-- >>> :{+--   sphericToVec'V3 :: (TrigField a, ExpField a, IntegerPower a, a ~ CT a) =>+--     (a, a) -> BoxedVector 3 (a, a)+--   sphericToVec'V3 = customArgValDerivative tupleArg autoVal sphericToVec+-- :}+--+-- Automatically deriving both the argument and value types+-- is often problematic due to type inference limitations in Haskell.+--+-- In summary, there are three common approaches to managing types+-- in the derivative operator for a function @f :: a -> b@:+--+-- 1. Define a derivative operator specialized for specific types @a@ and @b@.+--+-- 2. Define a derivative operator that is polymorphic in the result type @b@,+--    but has a fixed argument type @a@.+--    See section+--    [Structured Value Type](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value).+--+-- 3. Define a derivative operator that is polymorphic in the argument type @a@,+--    but has a fixed result type @b@.+--    See `scalarValDerivative` in the subsection+--    [Structured Argument Type](#g:differentiation-45-for-45-structured-45-types-45-structured-45-argument-45-type).++-- $differentiation-for-structured-types-structured-value+--+-- This section explains how to compute derivatives of functions whose values+-- have structured types (e.g., tuples, vectors, streams, or nested combinations).+--+-- We begin with+-- [basic examples](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value-45-basic-45-examples)+-- to demonstrate how derivatives work for common structured types.+--+-- Then, in+-- [custom derivative operators and value structure descriptors](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value-45-custom-45-derivative),+-- we explain how to define derivative operators for any structured value type using+-- custom descriptors.+--+-- In+-- [how it works: structured value types](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value-45-how-45-it-45-works),+-- we delve into the type signatures and the underlying idea behind value type descriptors.+--+-- Finally, in+-- [defining custom differentiable value types](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value-45-defining-45-custom-45-value-45-type),+-- we outline how to define your own differentiable types—beyond the scope+-- of the built-in descriptors provided by this package.++-- $differentiation-for-structured-types-structured-value-basic-examples+--+-- ==== Tuple-valued function+-- As a first example, we define a symbolic function @f@ of one variable+-- that returns a tuple of two values.+--+-- >>> :{+--   f :: TrigField a => a -> (a, a)+--   f t = (cos t, sin t)+-- :}+--+-- Define a symbolic variable @t@, as shown in the section+-- [Derivatives for Symbolic Expressions](#g:quick-45-start-45-derivatives-45-for-45-symbolic-45-expressions).+--+-- >>> t = variable "t"+-- >>> f t+-- (cos(t),sin(t))+--+-- The simplest way to take the derivative is to use the `scalarArgDerivative` operator,+-- which is polymorphic over the function's value type.+-- It is a polymorphic version of `customArgValDerivative` operator considered+-- in the beginning of the section+-- [Differentiation for Structured Types](#g:differentiation-45-for-45-structured-45-types)+-- It is defined as:+--+-- > scalarArgDerivative = customArgValDerivative scalarVal autoVal+--+-- The first argument `scalarVal` indicates that the function's argument type is scalar.+-- The second argument `autoVal` tells the system to infer the value type automatically.+--+-- The general type signature of `scalarArgDerivative` is discussed in a later section.+-- In this case, it simplifies to:+--+-- @+-- scalarArgDerivative :: Multiplicative (CT a) =>+--   (RevDiff a a -> (RevDiff a a, RevDiff a a)) ->+--   a ->+--   (CT a, CT a)+-- @+--+-- We can now compute derivatives as follows:+--+-- >>> f' = simplify . scalarArgDerivative f :: SE -> (SE, SE)+-- >>> f' t+-- (-(sin(t)),cos(t))+--+-- >>> f'' = simplify . scalarArgDerivative (scalarArgDerivative f) :: SE -> (SE, SE)+-- >>> f'' t+-- (-(cos(t)),-(sin(t)))+--+-- >>> (scalarArgDerivative (scalarArgDerivative f)) t :: (SE, SE)+-- (-(cos(t)*(1*1))+0,(-(sin(t))*(1*1))+0)+--+-- >>> temp t = -((cos t)*(one * one)) + zero+--+-- -- >>> (scalarArgDerivative temp) t :: SE+--+-- >>> import Debug.SimpleExpr.Utils.Algebra ((^))+--+-- >>> (scalarArgDerivative (scalarArgDerivative (scalarArgDerivative f))) (0.0 :: Float) :: (Float, Float)+-- (0.0,-1.0)+--+-- >>> (scalarArgDerivative exp) t :: SE+-- exp(t)*1+--+-- >>> (scalarArgDerivative (scalarArgDerivative (exp))) t :: SE+-- (exp(t)*(1*1))+0+--+-- >>> f''' = simplify . scalarArgDerivative (scalarArgDerivative (scalarArgDerivative f)) :: SE -> (SE, SE)+-- >>> f''' t+-- (sin(t),-(cos(t)))+--+-- Note that all derivateive function argiment types are the same+-- as the original function, but the value typea are different.+-- Here the the polymorphic preoperty of the `scalarArgDerivative` operator+-- comes into play, allowing us to differentiate functions without explicit+-- type annotations.+--+-- ==== Vector-valued function+-- In the next example, we take the derivative of a vector-valued symbolic function @v@+-- using boxed vectors from the+-- [vector-sized](https://hackage.haskell.org/package/vector-sized) library.+--+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- >>> :{+--   v :: SymbolicFunc a => a -> BoxedVector 3 a+--   v t = DVGS.fromTuple (+--      unarySymbolicFunc "v_x" t,+--      unarySymbolicFunc "v_y" t,+--      unarySymbolicFunc "v_z" t+--    )+-- :}+--+-- >>> v t+-- Vector [v_x(t),v_y(t),v_z(t)]+--+-- >>> v' = simplify . scalarArgDerivative v :: SE -> BoxedVector 3 SE+-- >>> v' t+-- Vector [v_x'(t),v_y'(t),v_z'(t)]+--+-- ==== Stream-valued function+-- Other data types, including lazy types such as streams from the+-- [stream](https://hackage.haskell.org/package/stream)+-- library,+-- can also be differentiated.+--+-- >>> :{+--   s :: SymbolicFunc a => a -> Stream a+--   s t = fromList [unarySymbolicFunc ("s_" <> show n) t | n <- [0..]]+-- :}+--+-- >>> take 5 (s t)+-- [s_0(t),s_1(t),s_2(t),s_3(t),s_4(t)]+--+-- >>> :{+--   s' :: SE -> Stream SE+--   s' = simplify . scalarArgDerivative s+-- :}+--+-- >>> take 5 (s' t)+-- [s_0'(t),s_1'(t),s_2'(t),s_3'(t),s_4'(t)]+--+-- ==== 4. Nested structured-valued function+-- We can also differentiate functions returning values in nested types. For example:+--+-- >>> :{+--   g :: SymbolicFunc a => a -> (BoxedVector 3 a, Stream a)+--   g t = (v t, s t)+-- :}+--+-- This function has the type @a -> (BoxedVector 3 a, Stream a)@.+-- Automatic differentiation remains straightforward:+--+-- >>> :{+--   g' :: SE -> (BoxedVector 3 SE, Stream SE)+--   g' = simplify . scalarArgDerivative g+-- :}+--+-- >>> fst $ g' t+-- Vector [v_x'(t),v_y'(t),v_z'(t)]+--+-- >>> take 5 $ snd $ g' t+-- [s_0'(t),s_1'(t),s_2'(t),s_3'(t),s_4'(t)]++-- $differentiation-for-structured-types-structured-value-custom-derivative+--+-- Instead of the polymorphic `scalarArgDerivative` operator,+-- which is defined as+--+-- > scalarArgDerivative = customArgValDerivative scalarArg autoVal+--+-- we can use a more specialized version tailored to the expected value type.+-- These customized derivatives still use `customArgValDerivative` with a specific+-- value structure descriptor but not `autoVal`.+--+-- ==== Tuple-valued function+--+-- Consider again the example from the previous subsection:+--+-- >>> scalarTupleDerivative = customArgValDerivative scalarArg tupleVal+--+-- Here, `scalarArg` indicates that+-- the input of the function being differentiated+-- is a scalar value, and+-- `tupleVal` indicates that the output of the function being differentiated+-- is a tuple of scalar values.+--+-- >>> :{+--   t :: SE+--   t = variable "t"+--   f :: TrigField a => a -> (a, a)+--   f t = (cos t, sin t)+--   f' :: SE -> (SE, SE)+--   f' = simplify . scalarTupleDerivative f+-- :}+--+-- >>> f' t+-- (-(sin(t)),cos(t))+--+-- ==== Vector-valued function+--+-- Similarly, we can define a derivative operator for a vector-valued function @v@:+--+-- >>> scalarTupleBoxedVectorDerivative = customArgValDerivative scalarArg boxedVectorVal+--+-- Here, `boxedVectorVal` declares that the function returns a boxed vector+-- of scalar values.+--+-- ==== Nested structured output function+--+-- In the third example from the previous subsection:+--+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- >>> :{+--   g :: SymbolicFunc a => a -> (BoxedVector 3 a, Stream a)+--   g = undefined+-- :}+--+-- the value type of @g@ is more sophisticated, so we must construct+-- a custom value structure manually:+--+-- >>> tupleBoxedVectorStreamVal = mkTupleVal (mkBoxedVectorVal scalarVal) (mkStreamVal scalarVal)+-- >>> scalarTupleBoxedVectorStreamDerivative = customArgValDerivative scalarArg tupleBoxedVectorStreamVal+-- >>> _ = scalarTupleBoxedVectorStreamDerivative g :: SE -> (BoxedVector 3 SE, Stream SE)+--+-- Here:+--+-- - 'mkTupleVal' constructs a value descriptor for a tuple,+-- - 'mkBoxedVectorVal' constructs a value descriptor for a boxed vector,+-- - 'mkStreamVal' constructs a value descriptor for a stream,+-- - and 'scalarVal' denotes the scalar leaf type.+--+-- In general, these building blocks combine to define custom value descriptors.+-- For example:+--+-- @+-- tupleVal       = mkTupleVal scalarVal+-- boxedVectorVal  = mkBoxedVectorVal scalarVal+-- streamVal      = mkStreamVal scalarVal+-- @+--+-- And for a scalar-valued function, we simply use:+--+-- > scalarScalarDerivative = customArgValDerivative scalarArg scalarVal++-- $differentiation-for-structured-types-structured-value-how-it-works+--+-- This section explains how the general backpropagation mechanism operates+-- at the level of function result (value) types.+--+-- ==== Derivative Operator Type Signature+--+-- To differentiate a scalar-to-scalar function @f :: a -> b@, we use its+-- differentiable form:+--+-- > f :: RevDiff a a -> RevDiff a b+--+-- (see the section+-- [How it works: core type `RevDiff`](#g:how-45-it-45-works-45-core-45-type-45-revdiff)).+--+-- For functions returning structured values, we generalize this to:+--+-- > f :: RevDiff a a -> c+--+-- where @c@ is a structured result built from `RevDiff a b` values.+-- We then use a \value structure descriptor\ of type @c -> d@+-- to extract the final derivative result @d@ from the structure @c@.+--+-- The resulting derivative operator has the following type:+--+-- @+-- scalarCustomArgDerivative ::+--   (c -> d) ->                 -- how to extract the final output+--   (RevDiff a a -> c) ->       -- the differentiable function+--   (a -> d)                    -- scalar input to final output+-- scalarCustomArgDerivative = customArgValDerivative scalarArg+-- @+--+-- Here, the first argument of type @c -> d@ transforms the intermediate structured result+-- into the final derivative value.+--+-- In fact, @scalarCustomArgDerivative@ is simply function composition:+--+-- > scalarCustomArgDerivative = (.)+--+-- ==== Value Descriptor Examples+--+-- Common value structure descriptors include in particular:+--+-- 1. /Scalar value/+--+-- > scalarVal :: Multiplicative (CT b) => RevDiff a b -> CT a+--+-- Converts a single differentiable value into a scalar result.+--+-- 2. /Tuple/+--+-- > tupleVal ::+-- >   (Multiplicative (CT b0), Multiplicative (CT b1)) =>+-- >   (RevDiff a0 b0, RevDiff a1 b1) -> (CT a0, CT a1)+--+-- Converts a tuple of differentiable values into a tuple of scalars.+--+-- 3. /Boxed Vector/+--+-- > boxedVectorVal ::+-- >   Multiplicative (CT b) =>+-- >   BoxedVector n (RevDiff a b) -> BoxedVector n (CT a)+--+-- Converts a boxed Vector of differentiable values into a boxed Vector of scalars.+--+-- 4. /Stream/+--+-- > streamVal ::+-- >   Multiplicative (CT b) =>+-- >   Stream (RevDiff a b) -> Stream (CT a)+--+-- Converts a stream of differentiable values into a stream of scalars.+--+-- 5. /Nested structure/+--+-- For example, a function returning a tuple of a boxed vector and a stream:+--+-- > tupleBoxedVectorStreamVal ::+-- >   Multiplicative (CT b) =>+-- >   (BoxedVector n (RevDiff a0 b0), Stream (RevDiff a1 b1)) ->+-- >   (BoxedVector n (CT a), Stream (CT a))+--+-- ==== Constructing Value Descriptors+--+-- You can construct value descriptors using standard higher-order functions:+--+-- @+-- mkTupleVal      :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1)+-- mkTupleVal      = cross+--+-- mkBoxedVectorVal :: (a -> b) -> BoxedVector n a -> BoxedVector n b+-- mkBoxedVectorVal = fmap+--+-- mkStreamVal     :: (a -> b) -> Stream a -> Stream b+-- mkStreamVal     = fmap+-- @+--+-- This means that to define a derivative for any custom structured type @MyType a@,+-- you only need to implement:+--+-- > myTypeVal :: Multiplicative (CT b) => MyType (RevDiff a b) -> MyType (CT a)+--+-- A typical approach is to define a mapping function:+--+-- > mkMyTypeVal :: (a -> b) -> MyType a -> MyType b+--+-- and then obtain the value descriptor by applying it to `scalarVal`:+--+-- > myTypeVal = mkMyTypeVal scalarVal+--+-- This approach allows you to differentiate functions returning arbitrarily+-- nested combinations of types, as we did above with tuple @(,)@,+-- `BoxedVector`@ n@, and `Stream`.++-- $differentiation-for-structured-types-structured-value-defining-custom-value-type+--+-- ==== Making Custom Scalar Type Differentiable+--+-- To make a scalar type @a@ differentiable, it is necessary and sufficient to:+--+-- 1. Define the type families `Tangent` for @a@ and `Dual` for `Tangent a`+--    (see [Tangent and Cotangent Spaces](#g:how-45-it-45-works-45-tangent-45-space)).+--+-- 2. Ensure that the type+--+-- > type CT a = Dual (Tangent a)+--+--    is an instance of `Multiplicative`.+--+-- The second condition is required to initialize the backpropagation process+-- with the value `one`.+--+-- ==== Making Custom Type Constructors Differentiable+--+-- To define derivatives over a custom type constructor @f :: Type -> Type@,+-- the recommended approach is:+--+-- 1. Define the /value descriptor/:+--+-- > mkFVal :: (a -> b) -> f a -> f b+--+-- In most cases, this is just `fmap`, or an optimized equivalent (see previous section).+--+-- 2. Provide an instance of the @AutoDifferentiableValue@ class:+--+-- > instance (AutoDifferentiableValue a b) =>+-- >   AutoDifferentiableValue (f a) (f b) where+-- >   autoVal :: f a -> f b+-- >   autoVal = mkFVal autoVal+--+-- This recursively applies `autoVal` within the structure of @f a@.+--+-- For more sophisticated custom types (e.g. higher-kinded types such as+-- @g :: Type -> Type -> Type@), refer to the implementation of the instance for+-- tuples @(,)@ in @AutoDifferentiableValue@ for guidance.++-- $differentiation-for-structured-types-structured-argument-type+--+-- In this section, we consider how to differentiate a function+-- with a structured or nontrivial argument type.+--+-- The simplest way to compute the derivative of a scalar-valued function (i.e. gradient)+-- is by using the `scalarValDerivative` operator.+-- This operator is polymorphic over the function’s argument type,+-- but it is restricted to functions that return scalar values.+--+-- In terms of the more general `customArgValDerivative` operator+-- [Differentiation for Structured Types](#g:differentiation-45-for-45-structured-45-types),+-- the `scalarValDerivative` is equivalent to:+--+-- > scalarValDerivative = customArgValDerivative autoArg scalarVal+--+-- Here, the first argument `autoArg` indicates that the argument type+-- (i.e. the structure of the input) is inferred automatically.+--+-- The second argument `scalarVal` specifies that the return value of the function+-- must be a scalar.++-- $differentiation-for-structured-types-structured-argument-type-basic-examples+--+-- ==== Gradient over the Euclidean Norm of a Vector+-- Our first example involves a function over a sized boxed vector,+-- `BoxedVector`. We define the squared Euclidean norm of a 3-dimensional vector:+--+-- >>> import Debug.SimpleExpr.Utils.Algebra (IntegerPower, (^), MultiplicativeAction)+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- >>> :{+--   eNorm2 :: (IntegerPower a, Additive a) => BoxedVector 3 a -> a+--   eNorm2 x = foldl' (+) zero (fmap (^2) x)+-- :}+--+-- This is not the most efficient way to define a function on large vectors,+-- but for this example, we focus on type signatures and type inference+-- rather than performance.+--+-- The gradient of @eNorm2@ can be computed as:+--+-- >>> :{+--   eNorm2' :: (+--       IntegerPower a,+--       MultiplicativeAction Integer a,+--       Distributive a,+--       CT a ~ a+--     ) => BoxedVector 3 a -> BoxedVector 3 a+--   eNorm2' = scalarValDerivative eNorm2+-- :}+--+-- As usual, `scalarValDerivative` can be applied to symbolic expressions,+-- such as values of type `SE`:+--+-- >>> x = variable "x"+-- >>> y = variable "y"+-- >>> z = variable "z"+-- >>> r = DVGS.fromTuple (x, y, z) :: BoxedVector 3 SE+-- >>> simplify $ eNorm2' r :: BoxedVector 3 SE+-- Vector [2*x,2*y,2*z]+--+-- It also works with numeric types like `Float`:+--+-- >>> v = DVGS.fromTuple (1, 2, 3) :: BoxedVector 3 Float+-- >>> eNorm2' v :: BoxedVector 3 Float+-- Vector [2.0,4.0,6.0]+--+-- ==== Gradient over a Stream+-- The `Stream` type can also be used as an argument.+-- However, note that the result of the gradient is not a `Stream`,+-- but rather a bounded stream: `FiniteSupportStream`.+-- See+-- [Tangent and Cotangent Spaces](#g:how-45-it-45-works-45-tangent-45-space)+-- for a brief explanation.+--+-- Define a formal series+--+-- \[+-- s = s_0, s_1, s_2, s_3, \ldots+-- \]+--+-- as:+--+-- >>> s = fromList [variable ("s_" <> show n) | n <- [0 :: Int ..]] :: Stream SE+--+-- Next, define a function that sums the first four elements of the stream:+--+-- \[+-- s \mapsto s_0 + s_1 + s_2 + s_3+-- \]+--+-- >>> take4Sum = NH.sum . take 4 :: Additive a => Stream a -> a+-- >>> simplify $ take4Sum s :: SE+-- s_0+(s_1+(s_2+s_3))+--+-- The gradient of this function can be defined as:+--+-- >>> :{+--  take4Sum' :: (Distributive a, Distributive (CT a)) =>+--    Stream a -> FiniteSupportStream (CT a)+--  take4Sum' = scalarValDerivative take4Sum+-- :}+--+-- >>> simplify $ take4Sum' s+-- [1,1,1,1,0,0,0,...+--+-- The result is a finite support stream of the form:+--+-- \[+-- 1, 1, 1, 1, 0, 0, 0, \ldots+-- \]+--+-- as expected.+--+-- ==== Gradinenet over Nested Structured Types+--+-- The `scalarValDerivative` operator can also handle more complex input types.+-- For example, consider a function @g@ that takes both a 3-vector and a stream:+--+-- >>> :{+--   g :: (IntegerPower a, Distributive a) =>+--     (BoxedVector 3 a, Stream a) -> a+--   g (v, s) = eNorm2 v + take4Sum s+-- :}+--+-- Its gradient can be computed as:+--+-- >>> :{+--   g' :: (IntegerPower a, MultiplicativeAction Integer a, Distributive a, CT a ~ a) =>+--     (BoxedVector 3 a, Stream a) -> (BoxedVector 3 a, FiniteSupportStream a)+--   g' = scalarValDerivative g+-- :}+--+-- Evaluating the gradient at @(r, s)@ gives:+--+-- >>> simplify $ fst $ g' (r, s) :: BoxedVector 3 SE+-- Vector [2*x,2*y,2*z]+--+-- >>> simplify $ snd $ g' (r, s) :: FiniteSupportStream SE+-- [1,1,1,1,0,0,0,...+--+-- as expected.++-- $differentiation-for-structured-types-structured-argument-type-custom-gradient+--+-- The `scalarValDerivative` operator from the previous section is polymorphic over+-- the argument type, but it works only for scalar-valued functions.+--+-- In this section, we consider how to /fix the argument type/ while keeping the+-- value type polymorphic. This is especially useful when computing second or higher-order+-- derivatives.+--+-- ==== Derivatives over a Tuple of Scalars+-- We begin with a function over a tuple of two scalars, which is equivalent+-- to a function of two arguments.+--+-- As an example, consider the product of symbolic functions @f@ and @g@ applied+-- to separate arguments:+--+-- >>> :{+--   x = variable "x"+--   y = variable "y"+--   f :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g :: SymbolicFunc a => a -> a+--   g = unarySymbolicFunc "g"+--   h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a+--   h (x, y) = f x * g y+-- :}+--+-- Evaluating @h@ at @(x, y)@ gives:+--+-- >>> h (x, y) :: SE+-- f(x)*g(y)+--+-- First, consider the derivative operator:+--+-- >>> tupleScalarDerivative = customArgValDerivative tupleArg scalarVal+--+-- It can be applied as follows:+--+-- >>> h' = simplify . tupleScalarDerivative h :: (SE, SE) -> (SE, SE)+-- >>> h' (x, y)+-- (f'(x)*g(y),g'(y)*f(x))+--+-- However, we cannot use @tupleScalarDerivative@ to compute the second derivative of @h@,+-- because it is restricted to scalar-valued functions. It is not polymorphic in the+-- value type, unlike `tupleArgDerivative`.+--+-- To define a version suitable for higher-order derivatives, we define:+--+-- > tupleArgDerivative = customArgValDerivative tupleArg autoVal+--+-- This operator is practically equivalent to `twoArgsDerivative` from the section+-- [Gradient over a Two-Argument Function](#g:quick-45-start-45-function-45-of-45-two-45-argument-45-functions),+-- except that it works on uncurried arguments.+--+-- We can now compute the derivative of @h@ as:+--+-- >>> :{+--   h' :: (SE, SE) -> (SE, SE)+--   h' = simplify . tupleArgDerivative h+-- :}+--+-- >>> h' (x, y)+-- (f'(x)*g(y),g'(y)*f(x))+--+-- Thanks to the polymorphism of `tupleArgDerivative`, we can compute higher-order+-- derivatives of @h@:+--+-- Second derivative:+--+-- >>> :{+--   h'' :: (SE, SE) -> ((SE, SE), (SE, SE))+--   h'' = simplify . tupleArgDerivative (tupleArgDerivative h)+-- :}+--+-- >>> h'' (x, y)+-- ((f''(x)*g(y),g'(y)*f'(x)),(f'(x)*g'(y),g''(y)*f(x)))+--+-- Third derivative:+--+-- >>> :{+--   h''' :: (SE, SE) -> (((SE, SE), (SE, SE)), ((SE, SE), (SE, SE)))+--   h''' = simplify . tupleArgDerivative (tupleArgDerivative (tupleArgDerivative h))+-- :}+--+-- >>> h''' (x, y)+-- (((f'''(x)*g(y),g'(y)*f''(x)),(f''(x)*g'(y),g''(y)*f'(x))),((f''(x)*g'(y),g''(y)*f'(x)),(f'(x)*g''(y),g'''(y)*f(x))))+--+-- ==== Derivatives over Boxed Vectors+-- The next example demonstrates derivatives over boxed vectors.+--+-- > boxedVectorArgDerivative = customArgValDerivative boxedVectorArg autoVal+--+-- Recall the function @eNorm2@, which computes the squared Euclidean norm+-- of a 3-dimensional vector:+--+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- >>> :{+--   eNorm2 :: Distributive a => BoxedVector 3 a -> a+--   eNorm2 x = foldl' (+) zero (x * x)+-- :}+--+-- We apply `boxedVectorArgDerivative` as follows:+--+-- >>> v = DVGS.fromTuple (1, 2, 3) :: BoxedVector 3 Float+-- >>> boxedVectorArgDerivative eNorm2 v :: BoxedVector 3 Float+-- Vector [2.0,4.0,6.0]+--+-- The second derivative gives the Hessian matrix represented here+-- as a boxed Vector of boxed Vectors:+--+-- >>> boxedVectorArgDerivative (boxedVectorArgDerivative eNorm2) v :: BoxedVector 3 (BoxedVector 3 Float)+-- Vector [Vector [2.0,0.0,0.0],Vector [0.0,2.0,0.0],Vector [0.0,0.0,2.0]]+--+-- The third derivative is a rank-3 tensor filled with zeros:+--+-- >>> boxedVectorArgDerivative (boxedVectorArgDerivative (boxedVectorArgDerivative eNorm2)) v :: BoxedVector 3 (BoxedVector 3 (BoxedVector 3 Float))+-- Vector [Vector [Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0]],Vector [Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0]],Vector [Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0],Vector [0.0,0.0,0.0]]]++-- $differentiation-for-structured-types-structured-argument-type-how-it-works+--+-- In order to compute a derivative, we need a function with the following signature:+--+-- > f :: RevDiff a a -> RevDiff a b+--+-- (See section+-- [Core type: RevDiff](#g:how-45-it-45-works-45-core-45-type-45-RevDiff).)+--+-- Suppose we want to differentiate a scalar-valued function of a tuple @(a, b)@:+--+-- > f :: (a, b) -> c+--+-- Our strategy is to exploit the polymorphism of @f@+-- with respect to the types @a@ and @b@.+-- This means that @f@ must also support the type:+--+-- > f :: (RevDiff t a, RevDiff t b) -> RevDiff t c+--+-- To differentiate such a function, we need a way to transform a single input of type+-- @RevDiff a (b0, b1)@ into a pair of inputs @(RevDiff a b0, RevDiff a b1)@.+--+-- This is exactly the role of the /argument structure derscriptor/:+--+-- > tupleArg :: (Additive (CT b0), Additive (CT b1)) =>+-- >   RevDiff a (b0, b1) -> (RevDiff a b0, RevDiff a b1)+--+-- Using this, we can define a new function:+--+-- > tupleArg . f :: RevDiff a (b0, b1) -> RevDiff a c+--+-- and apply `simpleDerivative`:+--+-- > simpleDerivative (tupleArg . f) :: (b0, b1) -> (CT b0, CT b1)+--+-- More generally, the expression:+--+-- > customArgValDerivative arg scalarVal f+--+-- is equivalent to:+--+-- > simpleDerivative (arg . f)+--+-- Similarly, we can define argument structure descriptor for Vectors and streams:+--+-- > boxedVectorArg :: (Additive (CT b), KnownNat n) =>+-- >   RevDiff a (BoxedVector n b) -> BoxedVector n (RevDiff a b)+--+-- > streamArg :: Additive (CT b) =>+-- >   RevDiff a (Stream b) -> Stream (RevDiff a b)+--+-- We can also combine them for more complex structured arguments.+-- For example:+--+-- >>> import Numeric.InfBackprop.Utils.SizedVector (BoxedVector)+--+-- >>> :{+--   tupleBoxedVectorStreamArg :: (Additive b, Additive c, KnownNat n) =>+--     RevDiff a (BoxedVector n b, FiniteSupportStream c) (BoxedVector n d, Stream e) -> (BoxedVector n (RevDiff a b d), Stream (RevDiff a c e))+--   tupleBoxedVectorStreamArg = cross boxedVectorArg streamArg . tupleArg+-- :}+--+-- This allows us to differentiate functions whose arguments have a nested structure,+-- such as @(BoxedVector n a, Stream a)@.+--+-- Alternatively, we can construct argument structure terms using the same style as for+-- value structure terms (see+-- [How it Works: Structured Value Types](#g:differentiation-45-for-45-structured-45-types-45-structured-45-value-45-how-45-it-45-works)):+--+-- >>> :{+--   tupleBoxedVectorStreamArgV2 :: (Additive b, Additive c, KnownNat n) =>+--     RevDiff a (BoxedVector n b, FiniteSupportStream c) (BoxedVector n d, Stream e) -> (BoxedVector n (RevDiff a b d), Stream (RevDiff a c e))+--   tupleBoxedVectorStreamArgV2 = mkTupleArg (mkBoxedVectorArg id) (mkStreamArg id)+-- :}+--+-- Note that:+--+-- > tupleArg       = mkTupleArg id+-- > boxedVectorArg  = mkBoxedVectorArg id+-- > streamArg      = mkStreamArg id+--+-- where `id` is used for scalar arguments.++-- $differentiation-for-structured-types-structured-argument-type-defining-custom-type+--+-- To support differentiation with respect to a custom scalar type @a@,+-- it is sufficient to define the associated type families:+--+-- - `Tangent`@ a@+-- - `Dual`@(@`Tangent`@a)@ (we denote this as `CT`@a@)+--+-- (See+-- [Tangent and Cotangent Spaces](#g:how-45-it-45-works-45-tangent-45-space)+-- for more details.)+--+-- Of course, you must also implement some differentiable function,+-- which is to be differentiated, for example:+--+-- > func :: RevDiff a a -> RevDiff a b+--+-- If @b@ is a scalar type,+-- the derivative will have the type:+--+-- > func' :: a -> CT a+--+-- For structured types like @f :: Type -> Type@, we recommend the following:+--+-- 1. Define the type families:+--+--    - `Tangent`@(f a)@+--+--    - `Dual`@ (@'Tangent`@ (f a))@+--+-- 2. Define the argument type descriptor, which is practically a permutation function:+--+-- > fArg :: Additive (CT b) =>+-- >   RevDiff a (f b) -> f (RevDiff a b)+--+-- 3. Define the argument type descriptor constructor:+--+-- > mkFArg :: Additive (CT b) =>+-- >   (RevDiff a b -> c) -> RevDiff a (f b) -> f c+--+-- 4. Provide an instance:+--+-- > instance (AutoDifferentiableArgument a b c, Additive (CT b)) =>+-- >   AutoDifferentiableArgument a (f b) (f c) where+-- >     autoArg = mkFArg autoArg+--+-- For bifunctor types @g :: Type -> Type -> Type@:+--+-- 1. Define type families:+--+--    - `Tangent`@(g a0 a1)@+--+--    - `Dual`@(@`Tangent`@(g a0 a1))@+--+-- 2. Define the argument type descriptor:+--+-- > gArg :: (Additive (CT b0), Additive (CT b1)) =>+-- >   RevDiff a (g b0 b1) -> g (RevDiff a b0) (RevDiff a b1)+--+-- 3. Define the argument type descriptor constructor:+--+-- > mkGArg :: (Additive (CT b0), Additive (CT b1)) =>+-- >   (RevDiff a b0 -> c0) ->+-- >   (RevDiff a b1 -> c1) ->+-- >   RevDiff a (g b0 b1) ->+-- >   g c0 c1+--+-- 4. Provide an instance:+--+-- > instance (+-- >     AutoDifferentiableArgument a b0 c0,+-- >     AutoDifferentiableArgument a b1 c1,+-- >     Additive (CT b0),+-- >     Additive (CT b1)+-- >   ) =>+-- >   AutoDifferentiableArgument a (g b0 b1) (g c0 c1) where+-- >     autoArg = mkGArg autoArg autoArg++-- $performance-remarks+--+-- This section discusses performance considerations when using the library.++-- $performance-remarks-subexpression-elimination+--+-- Some intermediate results computed during the forward pass+-- (see+-- [The Backpropagation Derivative](#g:how-45-it-45-works-45-backpropagation))+-- can be reused during the backward pass.+-- For deep neural networks, this reuse can result in significant computational savings.+-- This optimization can be viewed as a form of /subexpression elimination/—+-- a problem that Haskell’s evaluation model doesn't always handle automatically.+--+-- Consider the following example:+--+-- >>> :{+--   f, g, h :: SymbolicFunc a => a -> a+--   f = unarySymbolicFunc "f"+--   g = unarySymbolicFunc "g"+--   h = unarySymbolicFunc "h"+--   k :: BinarySymbolicFunc a => a -> a -> a+--   k = binarySymbolicFunc "k"+--   forwardV1 :: (SymbolicFunc a, BinarySymbolicFunc a, Additive a) => a -> a+--   forwardV1 x_ = k (g y) (h y) where y = f x_+-- :}+--+-- Here we define a function @forwardV1@ as a composition+-- of functions. The intermediate result @f x@ is bound to a variable @y@,+-- which is then passed to both @g@ and @h@.+--+-- To trace the evaluation of functions @f@, @g@, @h@, and @k@,+-- we use the `trace` function from @Debug.Trace@.+-- To facilitate this, we define a traced version @Traced@+-- of the symbolic expression type @SE@:+--+-- >>> x = MkTraced $ variable "x" :: Traced SE+--+-- For example:+--+-- >>> f x :: Traced SE+--  <<< TRACING: Calculating f of x >>>+-- f(x)+--+-- The output:+--+-- > <<< TRACING: Calculating f of x >>>+--+-- is produced by the `trace` mechanism.+--+-- Now consider the more complex function:+--+-- > >>> simplify $ forwardV1 x :: Traced SimpleExpr+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating g of f(x) >>>+-- >  <<< TRACING: Calculating h of f(x) >>>+-- >  <<< TRACING: Calculating k of g(f(x)) and h(f(x)) >>>+-- > k(g(f(x)),h(f(x)))+--+-- The output may vary in order, depending on GHC's optimizations, but importantly,+-- note that @f x@ is only computed once and its result is reused,+-- thanks to the local binding.+--+-- By contrast, if we define @forwardV2@+-- without explicitly factoring out the shared subexpression:+--+-- >>> :{+--   forwardV2 :: (SymbolicFunc a, BinarySymbolicFunc a, Additive a) => a -> a+--   forwardV2 x_ = k (g (f x_)) (h (f x_))+-- :}+--+-- the tracing output will show redundant evaluations:+--+-- > >>> simplify $ forwardV2 x :: Traced SimpleExpr+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating g of f(x) >>>+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating h of f(x) >>>+-- >  <<< TRACING: Calculating k of g(f(x)) and h(f(x)) >>>+-- > k(g(f(x)),h(f(x)))+--+-- Here, @f x@ is computed twice.+-- This illustrates that /GHC does not always automatically eliminate subexpressions/.+--+-- Now consider tracing the derivative of @forwardV1@.+-- In the long output below, observe that @f'@+-- is /not/ computed twice during the backward pass:+--+-- > >>> simplify $ simpleDerivative forwardV1 x :: Traced SimpleExpr+-- >  <<< TRACING: Calculating f' of x >>>+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating g' of f(x) >>>+-- >  <<< TRACING: Calculating g of f(x) >>>+-- >  <<< TRACING: Calculating h of f(x) >>>+-- >  <<< TRACING: Calculating k'_1 of g(f(x)) and h(f(x)) >>>+-- >  <<< TRACING: Calculating (*) of k'_1(g(f(x)),h(f(x))) and 1 >>>+-- >  <<< TRACING: Calculating (*) of g'(f(x)) and k'_1(g(f(x)),h(f(x)))*1 >>>+-- >  <<< TRACING: Calculating (*) of f'(x) and g'(f(x))*(k'_1(g(f(x)),h(f(x)))*1) >>>+-- >  <<< TRACING: Calculating h' of f(x) >>>+-- >  <<< TRACING: Calculating k'_2 of g(f(x)) and h(f(x)) >>>+-- >  <<< TRACING: Calculating (*) of k'_2(g(f(x)),h(f(x))) and 1 >>>+-- >  <<< TRACING: Calculating (*) of h'(f(x)) and k'_2(g(f(x)),h(f(x)))*1 >>>+-- >  <<< TRACING: Calculating (*) of f'(x) and h'(f(x))*(k'_2(g(f(x)),h(f(x)))*1) >>>+-- >  <<< TRACING: Calculating (+) of f'(x)*(g'(f(x))*(k'_1(g(f(x)),h(f(x)))*1)) and f'(x)*(h'(f(x))*(k'_2(g(f(x)),h(f(x)))*1)) >>>+-- > (f'(x)*(g'(f(x))*k'_1(g(f(x)),h(f(x)))))+(f'(x)*(h'(f(x))*k'_2(g(f(x)),h(f(x)))))+--+-- The possible duplication of becomes more severe as function composition grows deeper—+-- a major performance issue in neural network applications.+--+-- For further illustration, consider the first and second derivatives+-- of the composition @(g . f)@:+--+-- > >>> simpleDerivative (g . f) x :: Traced SimpleExpr+-- >  <<< TRACING: Calculating f' of x >>>+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating g' of f(x) >>>+-- >  <<< TRACING: Calculating (*) of g'(f(x)) and 1 >>>+-- >  <<< TRACING: Calculating (*) of f'(x) and g'(f(x))*1 >>>+-- > f'(x)*(g'(f(x))*1)+--+-- > >>> simpleDerivative (simpleDerivative (g . f)) x :: Traced SimpleExpr+-- >  <<< TRACING: Calculating f'' of x >>>+-- >  <<< TRACING: Calculating f of x >>>+-- >  <<< TRACING: Calculating g' of f(x) >>>+-- >  <<< TRACING: Calculating (*) of g'(f(x)) and 1 >>>+-- >  <<< TRACING: Calculating (*) of g'(f(x))*1 and 1 >>>+-- >  <<< TRACING: Calculating (*) of f''(x) and (g'(f(x))*1)*1 >>>+-- >  <<< TRACING: Calculating f' of x >>>+-- >  <<< TRACING: Calculating g'' of f(x) >>>+-- >  <<< TRACING: Calculating f' of x >>>+-- >  <<< TRACING: Calculating (*) of f'(x) and 1 >>>+-- >  <<< TRACING: Calculating (*) of 1 and f'(x)*1 >>>+-- >  <<< TRACING: Calculating (*) of g''(f(x)) and 1*(f'(x)*1) >>>+-- >  <<< TRACING: Calculating (*) of f'(x) and g''(f(x))*(1*(f'(x)*1)) >>>+-- >  <<< TRACING: Calculating (+) of f'(x)*(g''(f(x))*(1*(f'(x)*1))) and 0 >>>+-- >  <<< TRACING: Calculating (+) of f''(x)*((g'(f(x))*1)*1) and (f'(x)*(g''(f(x))*(1*(f'(x)*1))))+0 >>>+-- > (f''(x)*((g'(f(x))*1)*1))+((f'(x)*(g''(f(x))*(1*(f'(x)*1))))+0)+--+-- Here we observe that @f'(x)@ is computed /twice/ in the second derivative.+-- This occurs because it appears in two different branches of the expression tree:+-- once as the outer derivative, and once via the inner term @g'(f(x))@.+--+-- Unfortunately, the current implementation of `simplify` is /not able/ to eliminate+-- this redundancy, as it lacks full common subexpression elimination.+--+-- Nevertheless, for typical neural network applications,+-- the current backpropagation implementation for the first derivative+-- is performant enough in practice.++-- $performance-remarks-forward-step-results-reusage+--+-- Some results from the forward pass can be reused during the backward pass,+-- leading to significant computational savings. Let's explore this optimization+-- through a concrete example.+--+-- Consider differentiating the hyperbolic functions:+--+-- \[+-- \cosh x = \sinh' x = \frac{e^x + e^{-x}}{2}+-- \]+-- and+-- \[+-- \sinh x = \cosh' x = \frac{e^x - e^{-x}}{2}+-- \]+--+-- Notice that both functions require computing the same exponentials:+-- \(e^x\) and \(e^{-x}\).+-- During the forward pass, we calculate these exponentials to compute the function value.+-- Then, during the backward pass for derivative computation, we need exactly the same+-- exponentials again. Rather than recomputing them, we can reuse the forward pass results.+--+-- This optimization becomes particularly valuable when dealing with computationally+-- expensive operations, such as matrix exponentials, where avoiding redundant+-- calculations can dramatically improve performance.+--+-- While automatic subexpression elimination techniques exist, we'll explore a different+-- approach: manual subexpression elimination implemented directly in the backpropagation+-- definition. This gives us explicit control over which intermediate results to preserve+-- and reuse.+--+-- Here's how we implement this optimization:+--+-- We define an @ExpFieldV2@ typeclass that produces the same function values as+-- `ExpField`+-- but differs in how it handles intermediate computations, specifically designed to+-- enable result reuse:+--+-- >>> :{+--   class ExpFieldV2 a where+--     expV2 :: a -> a+--     sinhV2 :: a -> a+--     coshV2 :: a -> a+--   instance ExpFieldV2 SE where+--     expV2 = exp+--     sinhV2 x_ = (exp x_ - exp (negate x_)) / number 2+--     coshV2 x_ = (exp x_ + exp (negate x_)) / number 2+--   instance (ExpFieldV2 a, Distributive a, Subtractive a, Divisive a, FromInteger a) =>+--     ExpFieldV2 (RevDiff t a a) where+--       expV2 = simpleDifferentiableFunc expV2 expV2+--       sinhV2 (MkRevDiff x bpc) =+--         MkRevDiff ((expP - expM) NH./ fromInteger 2) (bpc . ((expP + expM) *)) where+--           expP = expV2 x+--           expM = expV2 (negate x)+--       coshV2 (MkRevDiff x bpc) =+--         MkRevDiff ((expP + expM) NH./ fromInteger 2) (bpc . ((expP - expM) *)) where+--           expP = expV2 x+--           expM = expV2 (negate x)+--   instance (ExpFieldV2 a, ExpField a, FromInteger a, Show a) =>+--     ExpFieldV2 (Traced a) where+--       expV2 = addTraceUnary "exp" expV2+--       sinhV2 x_ = (expV2 x_ - expV2 (negate x_)) / fromInteger 2+--       coshV2 x_ = (expV2 x_ + expV2 (negate x_)) / fromInteger 2+-- :}+--+-- The key insight is in the RevDiff instance: we manually store the exponentials+-- @expP@ (for \(e^x\)) and @expM@ (for \(e^{-x}\)) as local bindings.+-- This ensures they're+-- computed only once and then reused both for the forward value calculation and+-- the backward pass derivative computation.+--+-- Let's verify this optimization works as expected by tracing the computations:+--+-- >>> x = MkTraced $ variable "x" :: Traced SE+--+-- > >>> coshV2 x+-- >  <<< TRACING: Calculating exp of x >>>+-- >  <<< TRACING: Calculating negate of x >>>+-- >  <<< TRACING: Calculating exp of -(x) >>>+-- >  <<< TRACING: Calculating (+) of exp(x) and exp(-(x)) >>>+-- >  <<< TRACING: Calculating (/) of exp(x)+exp(-(x)) and 2 >>>+-- > (exp(x)+exp(-(x)))/2+--+-- Now let's examine what happens when we compute both the value and derivative.+-- To this end, we use a function `simpleValueAndDerivative`+-- that computes both the value and derivative:+--+-- > >>> simpleValueAndDerivative coshV2 x :: (Traced SE, Traced SE)+-- > ( <<< TRACING: Calculating exp of x >>>+-- >  <<< TRACING: Calculating negate of x >>>+-- >  <<< TRACING: Calculating exp of -(x) >>>+-- >  <<< TRACING: Calculating (+) of exp(x) and exp(-(x)) >>>+-- >  <<< TRACING: Calculating (/) of exp(x)+exp(-(x)) and 2 >>>+-- > (exp(x)+exp(-(x)))/2, <<< TRACING: Calculating (-) of exp(x) and exp(-(x)) >>>+-- >  <<< TRACING: Calculating (*) of exp(x)-exp(-(x)) and 1 >>>+-- > (exp(x)-exp(-(x)))*1)+--+-- Notice how the exponential calculations (exp of x and exp of -(x)) appear only+-- once in the trace, even though they're used in both the forward and backward passes.+-- This demonstrates that our manual subexpression elimination successfully avoids+-- redundant computations, reusing the exponential results as intended.+--+-- Moreover, we can compute the second derivative without recomputing the exponentials:+--+-- > >>> simpleDerivative (simpleDerivative coshV2) x :: Traced SE+-- >  <<< TRACING: Calculating exp of x >>>+-- >  <<< TRACING: Calculating (*) of 1 and 1 >>>+-- >  <<< TRACING: Calculating (*) of exp(x) and 1*1 >>>+-- >  <<< TRACING: Calculating negate of x >>>+-- >  <<< TRACING: Calculating exp of -(x) >>>+-- >  <<< TRACING: Calculating negate of 1*1 >>>+-- >  <<< TRACING: Calculating (*) of exp(-(x)) and -(1*1) >>>+-- >  <<< TRACING: Calculating negate of exp(-(x))*-(1*1) >>>+-- >  <<< TRACING: Calculating (+) of exp(x)*(1*1) and -(exp(-(x))*-(1*1)) >>>+-- >  <<< TRACING: Calculating (+) of (exp(x)*(1*1))+-(exp(-(x))*-(1*1)) and 0 >>>+-- > ((exp(x)*(1*1))+-(exp(-(x))*-(1*1)))+0++-- $what-is-next+--+-- Unboxed vectors and tensors are not currently supported in the library.
+ src/Numeric/InfBackprop/Utils/SizedVector.hs view
@@ -0,0 +1,63 @@+-- |+-- Module    :  Numeric.InfBackprop.Utils.CachedIso+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Utility functions for working with sized vector.+module Numeric.InfBackprop.Utils.SizedVector+  ( BoxedVector,+    boxedVectorBasis,+    boxedVectorSum,+  )+where++import Data.Finite (Finite)+import qualified Data.Vector as DV+import qualified Data.Vector.Generic as DVG+import qualified Data.Vector.Generic.Sized as DVGS+import GHC.Base (($), (==))+import GHC.TypeLits (Nat)+import GHC.TypeNats (KnownNat)+import NumHask (Additive, zero, (+))++-- | Type alias for boxed sized vectors.+type BoxedVector (n :: Nat) a = DVGS.Vector DV.Vector n a++-- | Creates a sized vector of size n with all elements set to @x :: a@+-- except for the one at index @k@, which is set to @y :: a@.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int, String)+-- >>> import qualified Data.Vector as DV+-- >>> import qualified Data.Vector.Generic.Sized as DVGS+--+-- >>> boxedVectorBasis 2 0 1 :: DVGS.Vector DV.Vector 4 Int+-- Vector [0,0,1,0]+--+-- >>> boxedVectorBasis 1 "zero" "one" :: DVGS.Vector DV.Vector 5 String+-- Vector ["zero","one","zero","zero","zero"]+boxedVectorBasis ::+  (DVG.Vector v a, KnownNat n) =>+  Finite n ->+  a ->+  a ->+  DVGS.Vector v n a+boxedVectorBasis k zero' one' = DVGS.generate $ \l ->+  if k == l+    then one'+    else zero'++-- | Sums all elements of a sized array.+--+-- ==== __Examples__+--+-- >>> import GHC.Base (Int)+-- >>> import qualified Data.Vector as DV+-- >>> import qualified Data.Vector.Generic.Sized as DVGS+--+-- >>> boxedVectorSum (DVGS.fromTuple (1, 2, 3) :: DVGS.Vector DV.Vector 3 Int)+-- 6+boxedVectorSum :: (Additive a) => DVGS.Vector DV.Vector n a -> a+boxedVectorSum = DVGS.foldl' (+) zero
+ src/Numeric/InfBackprop/Utils/Tuple.hs view
@@ -0,0 +1,121 @@+-- | Module    :  Numeric.InfBackprop.Instances.NumHask+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Utility functions for working with tuples.+module Numeric.InfBackprop.Utils.Tuple+  ( cross,+    cross3,+    fork,+    fork3,+    curry3,+    uncurry3,+    biCross,+    biCross3,+  )+where++-- | Applies two functions to the components of a tuple.++--- ==== __Examples__+--+-- >>> cross (+1) (*2) (3, 4)+-- (4,8)+cross :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)+{-# INLINE cross #-}+cross f g (x, y) = (f x, g y)++-- | Applies three functions to the components of a triple.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+), (-), (*))+--+-- >>> cross3 (+1) (*2) (\x -> x - 3) (3, 4, 10)+-- (4,8,7)+cross3 :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)+{-# INLINE cross3 #-}+cross3 f g h (x, y, z) = (f x, g y, h z)++-- | Applies two functions to the same argument and returns a tuple of results.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+), (*))+--+-- >>> fork (+1) (*2) 3+-- (4,6)+fork :: (t -> a) -> (t -> b) -> t -> (a, b)+{-# INLINE fork #-}+fork f g x = (f x, g x)++-- | Applies three functions to the same argument and returns a triple of results.+--+-- >>> import GHC.Num ((+), (-), (*))+--+-- ==== __Examples__+--+-- >>> fork3 (+1) (*2) (\x -> x - 3) 5+-- (6,10,2)+fork3 :: (t -> a0) -> (t -> a1) -> (t -> a2) -> t -> (a0, a1, a2)+{-# INLINE fork3 #-}+fork3 f0 f1 f2 x = (f0 x, f1 x, f2 x)++-- | Curries a function on triples.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+))+--+-- >>> f (x, y, z) = x + y + z+-- >>> g = curry3 f+-- >>> g 1 2 3+-- 6+curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d+{-# INLINE curry3 #-}+curry3 f x y z = f (x, y, z)++-- | Uncurries a function on triples.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+))+--+-- >>> f x y z = x + y + z+-- >>> g = uncurry3 f+-- >>> g (1, 2, 3)+-- 6+uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)+{-# INLINE uncurry3 #-}+uncurry3 f (x, y, z) = f x y z++-- | Applies two binary functions to the components of two tuples.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+), (*))+--+-- >>> biCross (+) (*) (1, 2) (3, 4)+-- (4,8)+biCross :: (a -> b -> c) -> (d -> e -> f) -> (a, d) -> (b, e) -> (c, f)+{-# INLINE biCross #-}+biCross f g (x0, x1) (y0, y1) = (f x0 y0, g x1 y1)++-- | Applies three binary functions to the components of two triples.+--+-- ==== __Examples__+--+-- >>> import GHC.Num ((+), (*), (-))+--+-- >>> biCross3 (+) (*) (-) (1, 2, 10) (3, 4, 5)+-- (4,8,5)+biCross3 ::+  (a -> b -> c) ->+  (d -> e -> f) ->+  (g -> h -> l) ->+  (a, d, g) ->+  (b, e, h) ->+  (c, f, l)+{-# INLINE biCross3 #-}+biCross3 f g h (x0, x1, x2) (y0, y1, y2) = (f x0 y0, g x1 y1, h x2 y2)
+ src/Numeric/InfBackprop/Utils/Vector.hs view
@@ -0,0 +1,164 @@+-- | Module    :  Numeric.InfBackprop.Instances.NumHask+-- Copyright   :  (C) 2025 Alexey Tochin+-- License     :  BSD3 (see the file LICENSE)+-- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>+--+-- Utility functions for working with vectors.+module Numeric.InfBackprop.Utils.Vector+  ( fromTuple,+    safeHead,+    safeLast,+    trimArrayHead,+    trimArrayTail,+    zipWith,+  )+where++import Control.Monad (MonadPlus, mzero)+import Data.Bool (otherwise)+import Data.Eq (Eq, (==))+import Data.Function (($))+import qualified Data.IndexedListLiterals as DILL+import Data.Maybe (Maybe (Just, Nothing))+import Data.Ord (Ordering (EQ, GT, LT), compare)+import qualified Data.Vector.Generic as DVG+import GHC.Base (pure, (.))++-- | Converts a tuple into a Vector (`Data.Vector.Vector`).+--+-- === __Examples__+--+-- >>> import GHC.Int (Int)+-- >>> import qualified Data.Vector as DV+--+-- >>> fromTuple (1 :: Int, 2 :: Int, 3 :: Int) :: DV.Vector Int+-- [1,2,3]+fromTuple ::+  (DVG.Vector v a) =>+  (DILL.IndexedListLiterals input length a) =>+  input ->+  v a+fromTuple = DVG.fromList . DILL.toList++-- | Returns the first element of a vector safely.+-- If the vector is empty, it returns 'Nothing'.+--+-- ==== __Examples__+--+-- >>> import GHC.Int (Int)+-- >>> import Data.Vector (fromList)+--+-- >>> safeHead (fromList [1, 2, 3]) :: Maybe Int+-- Just 1+--+-- >>> safeHead (fromList []) :: Maybe Int+-- Nothing+safeHead :: (DVG.Vector v a, MonadPlus m) => v a -> m a+safeHead vec+  | DVG.null vec = mzero+  | otherwise = pure $ DVG.unsafeHead vec++-- | Returns the last element of a vector safely.+-- If the vector is empty, it returns 'Nothing'.+--+-- ==== __Examples__+--+-- >>> import GHC.Int (Int)+-- >>> import Data.Vector (fromList, empty)+--+-- >>> safeLast (fromList [1, 2, 3]) :: Maybe Int+-- Just 3+--+-- >>> safeLast empty :: Maybe Int+-- Nothing+safeLast :: (DVG.Vector v a, MonadPlus m) => v a -> m a+safeLast vec+  | DVG.null vec = mzero+  | otherwise = pure $ DVG.unsafeLast vec++-- | Removes elements from the beginning of the vector until the first element+-- is not equal to the given value.+--+-- ==== __Examples__+--+-- >>> import Data.Vector (fromList, empty)+--+-- >>> trimArrayHead 1 (fromList [1, 1, 1, 2, 3])+-- [2,3]+--+-- >>> trimArrayHead 1 empty+-- []+trimArrayHead :: (DVG.Vector v a, Eq a) => a -> v a -> v a+trimArrayHead x vec = case safeHead vec of+  Nothing -> DVG.empty+  Just firstVal ->+    if firstVal == x+      then trimArrayHead x (DVG.tail vec)+      else vec++-- | Removes elements from the end of the vector until the last element+-- is not equal to the given value.+--+-- ==== __Examples__+--+-- >>> import Data.Vector (fromList, empty)+--+-- >>> trimArrayTail 3 (fromList [1, 2, 3, 3, 3])+-- [1,2]+--+-- >>> trimArrayTail 3 empty+-- []+trimArrayTail :: (DVG.Vector v a, Eq a) => a -> v a -> v a+trimArrayTail x array = case safeLast array of+  Nothing -> DVG.empty+  Just lastVal ->+    if lastVal == x+      then trimArrayTail x (DVG.init array)+      else array++-- | Combines two arrays of different lengths using a custom function.+-- The resulting array has a length equal to the maximum of the two input vectors.+-- The shorter array is padded with values generated by the provided functions.+--+-- ==== __Examples__+--+-- >>> import Prelude (id, negate, (-), Int)+-- >>> import qualified Data.Vector as DV+--+-- The following example demonstrates subtracting two arrays of different lengths.+-- The shorter array is padded with zeros, and the remaining elements are processed+-- using the provided functions.+--+-- >>>:{+--  zipWith+--    (-)                         -- Subtract corresponding elements from the two arrays+--    id                          -- Keep the remaining elements of the first array unchanged+--    negate                      -- Negate the remaining elements of the second array+--    (DV.fromList [10, 20, 30])  -- First array+--    (DV.fromList [1, 2])        -- Second array+-- :}+-- [9,18,30]+--+-- >>> import Prelude (id, negate, (-), Int)+-- >>> import Data.Vector (fromList)+--+-- >>> let v0 :: DV.Vector Int = DV.fromList [10, 20, 30]+-- >>> let v1 :: DV.Vector Int = DV.fromList [1, 2]+-- >>> zipWith (-) id negate v0 v1+-- [9,18,30]+zipWith ::+  (DVG.Vector v a, DVG.Vector v b, DVG.Vector v c) =>+  (a -> b -> c) ->+  (a -> c) ->+  (b -> c) ->+  v a ->+  v b ->+  v c+zipWith f g h a0 a1 = case compare l0 l1 of+  EQ -> base+  GT -> base DVG.++ DVG.map g (DVG.drop l1 a0)+  LT -> base DVG.++ DVG.map h (DVG.drop l0 a1)+  where+    l0 = DVG.length a0+    l1 = DVG.length a1+    base = DVG.zipWith f a0 a1
− src/Prelude/InfBackprop.hs
@@ -1,623 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- | Module    :  Prelude.InfBackprop--- Copyright   :  (C) 2023 Alexey Tochin--- License     :  BSD3 (see the file LICENSE)--- Maintainer  :  Alexey Tochin <Alexey.Tochin@gmail.com>------ Backpropagation differentiable versions of basic functions.-module Prelude.InfBackprop-  ( -- * Elementary functions-    linear,-    (+),-    (-),-    negate,-    (*),-    (/),--    -- * Tuple manipulations-    dup,-    setFirst,-    setSecond,-    forget,-    forgetFirst,-    forgetSecond,--    -- * Exponential family functions-    log,-    logBase,-    exp,-    (**),-    pow,--    -- * Trigonometric functions-    cos,-    sin,-    tan,-    asin,-    acos,-    atan,-    atan2,-    sinh,-    cosh,-    tanh,-    asinh,-    acosh,-    atanh,--    -- * Tools-    simpleDifferentiable,-  )-where--import Control.CatBifunctor (first, second, (***))-import Control.Category ((<<<), (>>>))-import InfBackprop.Common (Backprop (MkBackprop), BackpropFunc, const)-import IsomorphismClass.Isomorphism (iso)-import NumHask (Additive, Distributive, Divisive, ExpField, Subtractive, TrigField, fromInteger, zero)-import qualified NumHask as NH-import NumHask.Prelude (one)-import qualified NumHask.Prelude as NHP-import Prelude (flip, uncurry, ($), (==))-import qualified Prelude as P---- | Returns a differentiable morphism given forward function and backpropagation derivative differential morphism.------ ==== __Examples of usage__------ >>> import qualified NumHask as NH--- >>> cos = simpleDifferentiable NH.cos (sin >>> negate)-simpleDifferentiable :: forall x. Distributive x => (x -> x) -> BackpropFunc x x -> BackpropFunc x x-simpleDifferentiable f df = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = f--    forward' :: BackpropFunc x (x, x)-    forward' = dup >>> first (simpleDifferentiable f df)--    backward' :: BackpropFunc (x, x) x-    backward' = second df >>> (*)---- Tuple manipulations---- | Duplication differentiable operation.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call dup (42.0 :: Float)--- (42.0,42.0)------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> derivative (dup >>> (*)) x--- (1·x)+(1·x)-dup ::-  forall x.-  Additive x =>-  BackpropFunc x (x, x)-dup = MkBackprop call' forward' backward'-  where-    call' :: x -> (x, x)-    call' x = (x, x)-    forward' :: BackpropFunc x ((x, x), ())-    forward' = dup >>> (iso :: BackpropFunc y (y, ()))-    backward' :: BackpropFunc ((x, x), ()) x-    backward' = (iso :: BackpropFunc (y, ()) y) >>> (+)---- | Transforms any function to unit @()@.--- It is not differentiable until @StartBackprop@ is defined for @()@.--- However 'forget' is useful if need to remove some data in the differentiable pipeline.------ ==== __Examples of usage__------ >>> import InfBackprop (call, derivative)------ >>> f = first forget >>> (iso :: BackpropFunc ((), a) a) :: Additive a => BackpropFunc (a, a) a------ >>> call f (24, 42)--- 42------ >>> derivative f (24, 42)--- (0,1)-forget ::-  forall x.-  Additive x =>-  BackpropFunc x ()-forget = const ()---- | Remove the first element of a tuple.------ ==== __Examples of usage__------ >>> import InfBackprop (call, derivative)------ >>> call forgetFirst (24, 42)--- 42------ >>> derivative forgetFirst (24, 42)--- (0,1)-forgetFirst ::-  forall x y.-  Additive x =>-  BackpropFunc (x, y) y-forgetFirst = iso <<< first forget---- | Remove the second element of a tuple.------ ==== __Examples of usage__------ >>> import InfBackprop (call, derivative)------ >>> call forgetSecond (24, 42)--- 24------ >>> derivative forgetSecond (24, 42)--- (1,0)-forgetSecond ::-  forall x y.-  Additive y =>-  BackpropFunc (x, y) x-forgetSecond = iso <<< second forget---- | Transforms a 2-argument differentiable function into a single argument function by fixing its first argument.------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call (setFirst 8 (/)) 4 :: Float--- 2.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (setFirst x (*)) y--- 1·x-setFirst ::-  forall x y c.-  Additive c =>-  c ->-  BackpropFunc (c, x) y ->-  BackpropFunc x y-setFirst c f = (iso :: BackpropFunc x ((), x)) >>> first (const c) >>> f---- | Transforms a 2-argument differentiable function into a single argument function by fixing its second argument.------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call (setSecond 4 (/)) 8 :: Float--- 2.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (setSecond y (*)) x--- 1·y-setSecond ::-  forall x y c.-  Additive c =>-  c ->-  BackpropFunc (x, c) y ->-  BackpropFunc x y-setSecond c f = (iso :: BackpropFunc x (x, ())) >>> second (const c) >>> f---- Elementary functions---- | Linear differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (fmap, Float)--- >>> import InfBackprop (pow, call, derivative)--- >>> myFunc = linear 2 :: BackpropFunc Float Float------ >>> f = call myFunc :: Float -> Float--- >>> fmap f [-3, -2, -1, 0, 1, 2, 3]--- [-6.0,-4.0,-2.0,0.0,2.0,4.0,6.0]------ >>> df = derivative myFunc :: Float -> Float--- >>> fmap df [-3, -2, -1, 0, 1, 2, 3]--- [2.0,2.0,2.0,2.0,2.0,2.0,2.0]-linear ::-  forall x.-  NH.Distributive x =>-  x ->-  BackpropFunc x x-linear c = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = f c-      where-        f = (NH.*)-    forward' :: BackpropFunc x (x, ())-    forward' = linear c >>> (iso :: BackpropFunc y (y, ()))-    backward' :: BackpropFunc (x, ()) x-    backward' = (iso :: BackpropFunc (x, ()) x) >>> linear c---- | Summation differentiable binary operation.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)------ >>> call (+) (2, 3) :: Float--- 5.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (+) (x, y)--- (1,1)-(+) ::-  forall x.-  Additive x =>-  BackpropFunc (x, x) x-(+) = MkBackprop call' forward' backward'-  where-    call' :: (x, x) -> x-    call' = uncurry (NH.+)-    forward' :: BackpropFunc (x, x) (x, ())-    forward' = (+) >>> (iso :: BackpropFunc y (y, ()))-    backward' :: BackpropFunc (x, ()) (x, x)-    backward' = (iso :: BackpropFunc (x, ()) x) >>> dup---- | Negate differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (Float, ($))--- >>> import InfBackprop (call, derivative)------ >>> call negate 42 :: Float--- -42.0------ >>> derivative negate 42 :: Float--- -1.0-negate ::-  forall x.-  Subtractive x =>-  BackpropFunc x x-negate = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = NH.negate-    forward' :: BackpropFunc x (x, ())-    forward' = negate >>> (iso :: BackpropFunc y (y, ()))-    backward' :: BackpropFunc (x, ()) x-    backward' = (iso :: BackpropFunc (y, ()) y) >>> negate---- | Subtraction differentiable binary operation.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)------ >>> call (-) (5, 3) :: Float--- 2.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (-) (x, y)--- (1,-(1))-(-) :: forall x. (Subtractive x) => BackpropFunc (x, x) x-(-) = MkBackprop call' forward' backward'-  where-    call' :: (x, x) -> x-    call' = uncurry (NH.-)-    forward' :: BackpropFunc (x, x) (x, ())-    forward' = (-) >>> (iso :: BackpropFunc y (y, ()))-    backward' :: BackpropFunc (x, ()) (x, x)-    backward' = (iso :: BackpropFunc (x, ()) x) >>> dup >>> second negate---- | Product binnary operation------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call (*) (2, 3) :: Float--- 6.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (*) (x, y)--- (1·y,1·x)-(*) :: Distributive x => BackpropFunc (x, x) x-(*) = MkBackprop call' forward' backward'-  where-    call' :: Distributive x => (x, x) -> x-    call' = uncurry (NH.*)-    forward' :: Distributive x => BackpropFunc (x, x) (x, (x, x))-    forward' = dup >>> first (*)-    backward' :: Distributive x => BackpropFunc (x, (x, x)) (x, x)-    backward' =-      first dup-        >>> (iso :: BackpropFunc ((dy, dy), (x1, x2)) ((dy, x1), (dy, x2)))-        >>> (iso :: BackpropFunc (a, b) (b, a))-        >>> (*) *** (*)---- | Square differentiable operation------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call square 3 :: Float--- 9.0------ >>> derivative square 3 :: Float--- 6.0-square :: Distributive x => BackpropFunc x x-square = dup >>> (*)---- | Division binary differentiable operation------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call (/) (6, 3) :: Float--- 2.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> y = variable "y"--- >>> derivative (/) (x, y)--- (1·(1/y),1·(-(x)·(1/(y·y))))-(/) ::-  forall x.-  (Divisive x, Distributive x, Subtractive x) =>-  BackpropFunc (x, x) x-(/) = MkBackprop call' forward' backward'-  where-    call' :: (x, x) -> x-    call' = uncurry (NH./)-    forward' :: BackpropFunc (x, x) (x, (x, x))-    forward' = dup >>> first (/)-    backward' :: BackpropFunc (x, (x, x)) (x, x)-    backward' =-      dup *** dup-        >>> second (d1 *** d2) -- ((dy, dy), ((x1, x2), (x1, x2)))-        >>> (iso :: BackpropFunc ((dy, dy), (x1, x2)) ((dy, x1), (dy, x2))) -- ((dy, dy), (1 / x2, - x1 * x2^(-2) ))-        >>> (*) *** (*)-      where-        d1 = (forget *** recip) >>> (iso :: BackpropFunc ((), x) x) -- (x1, x2) -> 1 / x2-        d2 = (negate *** (square >>> recip)) >>> (*) -- (x1, x2) -> - x1 * x2^(-2)---- | The recip differentiable operation------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call recip 2 :: Float--- 0.5------ >>> derivative recip 2 :: Float--- -0.25-recip ::-  forall x.-  (Divisive x, Distributive x, Subtractive x) =>-  BackpropFunc x x-recip = setFirst NH.one (/)---- | Integer power differentiable operation------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call (pow 3) 2 :: Float--- 8.0------ >>> derivative (pow 3) 2 :: Float--- 12.0-pow ::-  forall x.-  ( Divisive x,-    Distributive x,-    Subtractive x,-    NH.FromIntegral x NHP.Integer-  ) =>-  NHP.Integer ->-  BackpropFunc x x-pow n = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = flip (NH.^) (fromInteger n)-    forward' :: BackpropFunc x (x, x)-    forward' = dup >>> first (pow n :: BackpropFunc x x)-    backward' :: BackpropFunc (x, x) x-    backward' = second der >>> (*)-      where-        der =-          if n == 0-            then const zero-            else pow (n P.- 1) >>> linear (NH.fromIntegral n)---- | Square root differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call sqrt 16 :: Float--- 4.0------ >>> derivative sqrt 16 :: Float--- 0.125-sqrt ::-  forall x.-  ExpField x =>-  BackpropFunc x x-sqrt = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = NH.sqrt-    forward' :: BackpropFunc x (x, x)-    forward' = (sqrt :: BackpropFunc x x) >>> dup-    backward' :: BackpropFunc (x, x) x-    backward' = second (recip >>> linear NH.half) >>> (*)---- | Power binary differentiable operation.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import NumHask (half)--- >>> import InfBackprop (call, derivative)--- >>> call (**) (0.5, 9) :: Float--- 3.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> n = variable "n"--- >>> derivative (**) (n, x)--- (1·(n·(x^(n-1))),1·((x^n)·log(x)))-(**) ::-  forall a.-  ( ExpField a,-    NH.FromIntegral a P.Integer-  ) =>-  BackpropFunc (a, a) a-(**) = MkBackprop call' forward' backward'-  where-    call' :: (a, a) -> a-    call' = uncurry $ flip (NH.**)-    forward' :: BackpropFunc (a, a) (a, (a, (a, a)))-    forward' =-      dup -- ((n, x), (n, x))-        >>> first ((**) >>> dup) -- ((x^n, x^n), (n, x))-        >>> (iso :: BackpropFunc ((a, b), c) (a, (b, c))) -- (x^n, (x^n, (n, x)))-    backward' :: BackpropFunc (a, (a, (a, a))) (a, a)-    backward' =-      dup *** (dup >>> (dn *** dx)) -- ((dy, dy), (dn, dx))-        >>> (iso :: BackpropFunc ((a, b), (c, d)) ((a, c), (b, d))) -- ((dy, dn), (dy, dx))-        >>> (*) *** (*)-      where-        -- (x^n, (n, x)) -> n * x^(n-1)-        dn :: BackpropFunc (a, (a, a)) a-        dn =-          forgetFirst -- (n, x)-            >>> first dup -- ((n, n), x)-            >>> (iso :: BackpropFunc ((a, b), c) (a, (b, c))) -- (n, (n, x))-            >>> second (first (setSecond (NH.fromIntegral (1 :: P.Integer)) (-))) -- (n, (n-1, x))-            >>> second (**) -- (n, x^(n-1))-            >>> (*) -- (n * x^(n-1))-            -- (x^n, (n, x)) -> log x * x^n-        dx :: BackpropFunc (a, (a, a)) a-        dx = second forgetFirst >>> second log >>> (*)---- | Natural logarithm differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call log 10 :: Float--- 2.3025851------ >>> derivative log 10 :: Float--- 0.1-log :: ExpField x => BackpropFunc x x-log = simpleDifferentiable NH.log recip---- | Natural logarithm differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call logBase (2, 8) :: Float--- 3.0------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> n = variable "n"--- >>> derivative logBase (n, x)--- ((1·(-(log(x))·(1/(log(n)·log(n)))))·(1/n),(1·(1/log(n)))·(1/x))-logBase :: ExpField a => BackpropFunc (a, a) a-logBase = (iso :: BackpropFunc (c, d) (d, c)) >>> log *** log >>> (/)---- | Natural logarithm differentiable function.------ ==== __Examples of usage__------ >>> import Prelude (Float)--- >>> import InfBackprop (call, derivative)--- >>> call exp 2--- 7.38905609893065------ >>> import Debug.SimpleExpr.Expr (variable)--- >>> x = variable "x"--- >>> derivative exp x--- 1·exp(x)-exp :: forall x. ExpField x => BackpropFunc x x-exp = MkBackprop call' forward' backward'-  where-    call' :: x -> x-    call' = NH.exp-    forward' :: BackpropFunc x (x, x)-    forward' = (exp :: BackpropFunc x x) >>> dup-    backward' :: BackpropFunc (x, x) x-    backward' = (*)---- Trigonometric---- | Sine differentiable function-sin :: TrigField x => BackpropFunc x x-sin = simpleDifferentiable NH.sin cos---- | Cosine differentiable function.-cos :: TrigField x => BackpropFunc x x-cos = simpleDifferentiable NH.cos (sin >>> negate)---- | Tangent differentiable function.-tan :: TrigField x => BackpropFunc x x-tan = simpleDifferentiable NH.tan (cos >>> square >>> recip)---- | Arcsine differentiable function.-asin :: (TrigField x, ExpField x) => BackpropFunc x x-asin = simpleDifferentiable NH.tan (square >>> setFirst one (-) >>> sqrt >>> recip)---- | Arccosine differentiable function.-acos :: (TrigField x, ExpField x) => BackpropFunc x x-acos = simpleDifferentiable NH.tan (square >>> setFirst one (-) >>> sqrt >>> recip >>> negate)---- | Arctangent differentiable function.-atan :: TrigField x => BackpropFunc x x-atan = simpleDifferentiable NH.atan (square >>> setFirst one (+) >>> recip)---- | 2-argument arctangent differentiable function.-atan2 :: TrigField a => BackpropFunc (a, a) a-atan2 = (/) >>> atan---- | Hyperbolic sine differentiable function.-sinh :: TrigField x => BackpropFunc x x-sinh = simpleDifferentiable NH.sinh cosh---- | Hyperbolic cosine differentiable function.-cosh :: TrigField x => BackpropFunc x x-cosh = simpleDifferentiable NH.cosh sinh---- | Hyperbolic tanget differentiable function.-tanh :: TrigField x => BackpropFunc x x-tanh = simpleDifferentiable NH.tanh (cosh >>> square >>> recip)---- | Hyperbolic arcsine differentiable function.-asinh :: (TrigField x, ExpField x) => BackpropFunc x x-asinh = simpleDifferentiable NH.asinh (square >>> setFirst one (+) >>> sqrt >>> recip)---- | Hyperbolic arccosine differentiable function.-acosh :: (TrigField x, ExpField x) => BackpropFunc x x-acosh = simpleDifferentiable NH.tan (square >>> setSecond one (-) >>> sqrt >>> recip)---- | Hyperbolic arctangent differentiable function.-atanh :: TrigField x => BackpropFunc x x-atanh = simpleDifferentiable NH.tan (square >>> setFirst one (-) >>> recip)