inf-backprop-0.2.0.0: Automatic differentiation and backpropagation.
Copyright(C) 2025 Alexey Tochin
LicenseBSD3 (see the file LICENSE)
MaintainerAlexey Tochin <Alexey.Tochin@gmail.com>
Safe HaskellNone
LanguageHaskell2010

Numeric.InfBackprop

Description

| 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.

Synopsis

Common

Base

type family Tangent a Source #

Converts a type into its tangent space type.

Instances

Instances details
type Tangent SimpleExpr Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent SimpleExpr = SimpleExpr
type Tangent Integer Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent Float Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Stream a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Stream a) = Stream (Tangent a)
type Tangent (FiniteSupportStream a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Complex a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Traced a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Traced a) = Traced (Tangent a)
type Tangent (Maybe a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Maybe a) = Maybe (Tangent a)
type Tangent [a] Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent [a] = [Tangent a]
type Tangent (Vec n a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Vec n a) = Vec n (Tangent a)
type Tangent (a0, a1) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (a0, a1) = (Tangent a0, Tangent a1)
type Tangent (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (RevDiff a b c) = RevDiff a (Tangent b) (Tangent c)
type Tangent (Vector v n a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (Vector v n a) = Vector v n (Tangent a)
type Tangent (a0, a1, a2) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (a0, a1, a2) = (Tangent a0, Tangent a1, Tangent a2)

type family Dual x Source #

Converts a type into its dual space type.

Instances

Instances details
type Dual SimpleExpr Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual SimpleExpr = SimpleExpr
type Dual Integer Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual Float Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Stream a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (FiniteSupportStream a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Complex a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Complex a) = Complex (Dual a)
type Dual (SimpleExprF a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (SimpleExprF a) = SimpleExprF (Dual a)
type Dual (Traced a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Traced a) = Traced (Dual a)
type Dual (Maybe a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Maybe a) = Maybe (Dual a)
type Dual [a] Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual [a] = [Dual a]
type Dual (Vec n a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Vec n a) = Vec n (Dual a)
type Dual (a, b) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (a, b) = (Dual a, Dual b)
type Dual (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (RevDiff a b c) = RevDiff a (Dual b) (Dual c)
type Dual (Vector v n a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (Vector v n a) = Vector v n (Dual a)
type Dual (a, b, c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (a, b, c) = (Dual a, Dual b, Dual c)

type Cotangent a = Dual (Tangent a) Source #

Cotangent type alias.

type CT a = Cotangent a Source #

Cotangent type alias.

data RevDiff a b c Source #

Base type for differentiable instances with the backpropagation.

Examples

Expand
>>> :{
 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

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 Num operations including arithmetic operators (+), (-), (*), comparison functions (abs, signum), and automatic conversion from integer literals via fromInteger.

Examples

Expand
>>> 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 Num instance, we would need explicit conversion:

>>> simplify $ twoArgsDerivativeOverY (*) x (stopDiff $ number 2) :: SE
x

With the Num instance for RevDiff, this simplifies to:

>>> simplify $ twoArgsDerivativeOverY (*) x (number 2) :: SE
x

And combined with the 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

Fractional typeclass instance

Thank to this instance we can use numerical literals like '1.0', '2.0', etc., see the examples below.

Examples

Expand
>>> 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)

Constructors

MkRevDiff 

Fields

Instances

Instances details
(HasConstant a b c d, Additive t, e ~ CT c, f ~ CT d) => HasConstant a b (RevDiff t e c) (RevDiff t f d) Source #

Recursive case: constant function for RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

constant :: Proxy a -> b -> RevDiff t e c -> RevDiff t f d Source #

(StopDiff a d, Additive b) => StopDiff a (RevDiff b c d) Source #

Recursive case: stopping differentiation for RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

stopDiff :: a -> RevDiff b c d Source #

(AlgebraicPower Integer a, MultiplicativeAction Integer a, Multiplicative a) => AlgebraicPower Integer (RevDiff c a a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Methods

(^^) :: RevDiff c a a -> Integer -> RevDiff c a a

(AlgebraicPower Int a, MultiplicativeAction Int a, Multiplicative a) => AlgebraicPower Int (RevDiff c a a) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Methods

(^^) :: RevDiff c a a -> Int -> RevDiff c a a

(MultiplicativeAction Integer b, MultiplicativeAction Integer cb) => MultiplicativeAction Integer (RevDiff ct cb b) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Methods

(*|) :: Integer -> RevDiff ct cb b -> RevDiff ct cb b

Costrong (RevDiff t) Source #

Costrong instance for RevDiff.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

unfirst :: RevDiff t (a, d) (b, d) -> RevDiff t a b #

unsecond :: RevDiff t (d, a) (d, b) -> RevDiff t a b #

Profunctor (RevDiff t) Source #

Profunctor instance for RevDiff.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

dimap :: (a -> b) -> (c -> d) -> RevDiff t b c -> RevDiff t a d #

lmap :: (a -> b) -> RevDiff t b c -> RevDiff t a c #

rmap :: (b -> c) -> RevDiff t a b -> RevDiff t a c #

(#.) :: forall a b c q. Coercible c b => q b c -> RevDiff t a b -> RevDiff t a c #

(.#) :: forall a b c q. Coercible b a => RevDiff t b c -> q a b -> RevDiff t a c #

Generic (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Associated Types

type Rep (RevDiff a b c) 
Instance details

Defined in Numeric.InfBackprop.Core

type Rep (RevDiff a b c) = D1 ('MetaData "RevDiff" "Numeric.InfBackprop.Core" "inf-backprop-0.2.0.0-inplace" 'False) (C1 ('MetaCons "MkRevDiff" 'PrefixI 'True) (S1 ('MetaSel ('Just "value") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 c) :*: S1 ('MetaSel ('Just "backprop") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (b -> a))))

Methods

from :: RevDiff a b c -> Rep (RevDiff a b c) x #

to :: Rep (RevDiff a b c) x -> RevDiff a b c #

(Additive a, Subtractive a, Num b, Subtractive b, Multiplicative b) => Num (RevDiff a b b) Source #

RevDiff instance for the Num typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

(+) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

(-) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

(*) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

negate :: RevDiff a b b -> RevDiff a b b #

abs :: RevDiff a b b -> RevDiff a b b #

signum :: RevDiff a b b -> RevDiff a b b #

fromInteger :: Integer -> RevDiff a b b #

(Additive a, Subtractive a, Subtractive b, Divisive b, Fractional b, IntegerPower b) => Fractional (RevDiff a b b) Source #

RevDiff instance for the Fractional typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

(/) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

recip :: RevDiff a b b -> RevDiff a b b #

fromRational :: Rational -> RevDiff a b b #

(Show (b -> a), Show c) => Show (RevDiff a b c) Source #

RevDiff instance for the Show typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

showsPrec :: Int -> RevDiff a b c -> ShowS #

show :: RevDiff a b c -> String #

showList :: [RevDiff a b c] -> ShowS #

(BinarySymbolicFunc a, Distributive a, Additive t) => BinarySymbolicFunc (RevDiff t a a) Source #

RevDiff instance of BinarySymbolicFunc typeclass.

Instance details

Defined in Debug.DiffExpr

Methods

binarySymbolicFunc :: String -> RevDiff t a a -> RevDiff t a a -> RevDiff t a a Source #

(SymbolicFunc a, Multiplicative a) => SymbolicFunc (RevDiff t a a) Source #

RevDiff instance of SymbolicFunc typeclass.

Instance details

Defined in Debug.DiffExpr

Methods

unarySymbolicFunc :: String -> RevDiff t a a -> RevDiff t a a Source #

(Additive a, Additive b) => AutoDifferentiableArgument (RevDiff a b c) Source #

AutoDifferentiableArgument instance for the scalar argument term.

Instance details

Defined in Numeric.InfBackprop.Core

Associated Types

type DerivativeRoot (RevDiff a b c) 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeRoot (RevDiff a b c) = a
type DerivativeCoarg (RevDiff a b c) 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeCoarg (RevDiff a b c) = b
type DerivativeArg (RevDiff a b c) 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeArg (RevDiff a b c) = c
Multiplicative b => AutoDifferentiableValue (RevDiff a b c) Source #

AutoDifferentiableValue instance for the scalar value term.

Instance details

Defined in Numeric.InfBackprop.Core

Associated Types

type DerivativeValue (RevDiff a b c) 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeValue (RevDiff a b c) = a

Methods

autoVal :: RevDiff a b c -> DerivativeValue (RevDiff a b c) Source #

(Additive a, Additive c) => Additive (RevDiff a b c) Source #

Additive instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

(+) :: RevDiff a b c -> RevDiff a b c -> RevDiff a b c #

zero :: RevDiff a b c #

(Additive a, Subtractive a, Subtractive b, Subtractive c) => Subtractive (RevDiff a b c) Source #

Subtractive instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

negate :: RevDiff a b c -> RevDiff a b c #

(-) :: RevDiff a b c -> RevDiff a b c -> RevDiff a b c #

(ExpField b, Additive a, Subtractive a, IntegerPower b) => ExpField (RevDiff a b b) Source #

ExpField instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

exp :: RevDiff a b b -> RevDiff a b b #

log :: RevDiff a b b -> RevDiff a b b #

(**) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

logBase :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

sqrt :: RevDiff a b b -> RevDiff a b b #

(Additive a, Subtractive a, ExpField b, TrigField b, IntegerPower b) => TrigField (RevDiff a b b) Source #

TrigField instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

pi :: RevDiff a b b #

sin :: RevDiff a b b -> RevDiff a b b #

cos :: RevDiff a b b -> RevDiff a b b #

tan :: RevDiff a b b -> RevDiff a b b #

asin :: RevDiff a b b -> RevDiff a b b #

acos :: RevDiff a b b -> RevDiff a b b #

atan :: RevDiff a b b -> RevDiff a b b #

atan2 :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

sinh :: RevDiff a b b -> RevDiff a b b #

cosh :: RevDiff a b b -> RevDiff a b b #

tanh :: RevDiff a b b -> RevDiff a b b #

asinh :: RevDiff a b b -> RevDiff a b b #

acosh :: RevDiff a b b -> RevDiff a b b #

atanh :: RevDiff a b b -> RevDiff a b b #

(Additive a, Divisive b, Subtractive b, IntegerPower b) => Divisive (RevDiff a b b) Source #

Divisive instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

recip :: RevDiff a b b -> RevDiff a b b #

(/) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

(Additive a, Multiplicative b) => Multiplicative (RevDiff a b b) Source #

Multiplicative instance for the RevDiff type.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

(*) :: RevDiff a b b -> RevDiff a b b -> RevDiff a b b #

one :: RevDiff a b b #

(FromInteger c, Additive a) => FromInteger (RevDiff a b c) Source #

RevDiff instance of the FromInteger typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromInteger :: Integer -> RevDiff a b c #

(FromIntegral c Int16, Additive a) => FromIntegral (RevDiff a b c) Int16 Source #

RevDiff and Int16 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Int16 -> RevDiff a b c #

(FromIntegral c Int32, Additive a) => FromIntegral (RevDiff a b c) Int32 Source #

RevDiff and Int32 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Int32 -> RevDiff a b c #

(FromIntegral c Int64, Additive a) => FromIntegral (RevDiff a b c) Int64 Source #

RevDiff and Int64 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Int64 -> RevDiff a b c #

(FromIntegral c Int8, Additive a) => FromIntegral (RevDiff a b c) Int8 Source #

RevDiff and Int8 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Int8 -> RevDiff a b c #

(FromIntegral c Word16, Additive a) => FromIntegral (RevDiff a b c) Word16 Source #

RevDiff and Word16 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Word16 -> RevDiff a b c #

(FromIntegral c Word32, Additive a) => FromIntegral (RevDiff a b c) Word32 Source #

RevDiff and Word32 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Word32 -> RevDiff a b c #

(FromIntegral c Word64, Additive a) => FromIntegral (RevDiff a b c) Word64 Source #

RevDiff and Word64 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Word64 -> RevDiff a b c #

(FromIntegral c Word8, Additive a) => FromIntegral (RevDiff a b c) Word8 Source #

RevDiff and Word8 instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Word8 -> RevDiff a b c #

(FromIntegral c Integer, Additive a) => FromIntegral (RevDiff a b c) Integer Source #

RevDiff and Integer instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Integer -> RevDiff a b c #

(FromIntegral c Natural, Additive a) => FromIntegral (RevDiff a b c) Natural Source #

RevDiff and Natural instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Natural -> RevDiff a b c #

(FromIntegral c Int, Additive a) => FromIntegral (RevDiff a b c) Int Source #

RevDiff and Int instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Int -> RevDiff a b c #

(FromIntegral c Word, Additive a) => FromIntegral (RevDiff a b c) Word Source #

RevDiff and Word instance of the FromIntegral typeclass.

Instance details

Defined in Numeric.InfBackprop.Core

Methods

fromIntegral :: Word -> RevDiff a b c #

(MultiplicativeAction a b, MultiplicativeAction a cb, Convolution b cb ca, Additive ct) => MultiplicativeAction (RevDiff ct ca a) (RevDiff ct cb b) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Methods

(*|) :: RevDiff ct ca a -> RevDiff ct cb b -> RevDiff ct cb b

(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) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

Methods

(|*|) :: RevDiff ct ca a -> RevDiff ct cb b -> RevDiff ct cc c

type Rep (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Rep (RevDiff a b c) = D1 ('MetaData "RevDiff" "Numeric.InfBackprop.Core" "inf-backprop-0.2.0.0-inplace" 'False) (C1 ('MetaCons "MkRevDiff" 'PrefixI 'True) (S1 ('MetaSel ('Just "value") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 c) :*: S1 ('MetaSel ('Just "backprop") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (b -> a))))
type DerivativeArg (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeArg (RevDiff a b c) = c
type DerivativeCoarg (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeCoarg (RevDiff a b c) = b
type DerivativeRoot (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeRoot (RevDiff a b c) = a
type DerivativeValue (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type DerivativeValue (RevDiff a b c) = a
type Dual (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Dual (RevDiff a b c) = RevDiff a (Dual b) (Dual c)
type Tangent (RevDiff a b c) Source # 
Instance details

Defined in Numeric.InfBackprop.Core

type Tangent (RevDiff a b c) = RevDiff a (Tangent b) (Tangent c)

type RevDiff' a b = RevDiff (CT a) (CT b) b Source #

Type alias for common case where the backpropagation is in the cotangent space.

type DifferentiableFunc a b = forall t. RevDiff t (CT a) a -> RevDiff t (CT b) b Source #

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

Expand
>>> :{
 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

initDiff :: a -> RevDiff b b a Source #

Initializes a MkRevDiff instance with given value and identity backpropagation function. This is useful for starting the backpropagation chain.

Examples

Expand
>>> :{
  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

call :: (RevDiff' a a -> RevDiff' a b) -> a -> b Source #

Converts a differentiable function into a regular function.

Examples

Expand
>>> 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)

derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a Source #

Converts a differentiable function into into its derivative in the form of multiplicative operator.

Examples

Expand
>>> 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

constDiff :: Additive a => c -> RevDiff a b c Source #

Creates a constant differentiable function. The derivative of a constant function is always zero.

Examples

Expand
>>> value (constDiff 42.0 :: RevDiff' Float Float)
42.0
>>> backprop (constDiff 42.0 :: RevDiff' Float Float) 1.0
0.0

scalarArg :: RevDiff a b c -> RevDiff a b c Source #

Scalar (trivial) argument descriptor for differentiable functions.

Examples

Expand
>>> 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)]

scalarVal :: Multiplicative b => RevDiff a b c -> a Source #

Scalar value term.

Examples

Expand
>>> :{
   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)

autoArg :: AutoDifferentiableArgument a => RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a Source #

Automatic argument descriptor.

autoVal :: AutoDifferentiableValue a => a -> DerivativeValue a Source #

Automatic value descriptor.

stopDiff :: StopDiff a b => a -> b Source #

Stops differentiation by converting a nested RevDiff type into a non-differentiable type.

simpleDifferentiableFunc :: Multiplicative b => (b -> b) -> (b -> b) -> RevDiff a b b -> RevDiff a b b Source #

Creates a differentiable function from a function and its derivative. This is a convenience function for defining new differentiable operations.

Examples

Expand
>>> :{
 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

Relation to lens and profunctors

toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca) Source #

Converts a function into a pair of its value and backpropagation function, which are the lense get and set functions, respectively.

toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d Source #

Converts a differentiable function into a law-breaking Lens. This is mutually inverse with fromLens.

Examples

Expand
>>> 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)

fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b Source #

Converts a law-breaking Lens into a differentiable function. This is mutually inverse with toLens.

Examples

Expand
>>> 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)

fromProfunctors :: (forall (p :: Type -> Type -> Type). Costrong p => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b Source #

Transorfms profunctor (Costrong) map into a RevDiff map. Inverse of toProfunctors.

toProfunctors :: Costrong p => DifferentiableFunc a b -> p (CT a) a -> p (CT b) b Source #

Profunctor representation of the RevDiff like for lens map in the spirit of optics. Inverse of fromProfunctors.

fromVanLaarhoven :: forall a b. (forall (f :: Type -> Type). Functor f => (b -> f (CT b)) -> a -> f (CT a)) -> DifferentiableFunc a b Source #

Converts a Van Laarhoven representation to a function over RevDiff types Inverse of toVanLaarhoven.

toVanLaarhoven :: Functor f => DifferentiableFunc a b -> (b -> f (CT b)) -> a -> f (CT a) Source #

Converts a function over RevDiff types into a Van Laarhoven representation. Inverse of fromVanLaarhoven.

Derivative operators

scalarArgDerivative :: AutoDifferentiableValue c => (RevDiff' a a -> c) -> a -> DerivativeValue c Source #

Derivative operator for a function from a scalar to any supported value type.

Examples

Expand
>>> 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))

customArgDerivative :: AutoDifferentiableValue c => (RevDiff (CT a) (CT a) a -> b) -> (b -> c) -> a -> DerivativeValue c Source #

Derivative operator for a function with a specified argument type, but with the value type derived automatically.

Examples

Expand
>>> :{
   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)]

customValDerivative :: (DerivativeRoot b ~ CT (DerivativeArg b), DerivativeCoarg b ~ CT (DerivativeArg b), AutoDifferentiableArgument b) => (c -> d) -> (b -> c) -> DerivativeArg b -> d Source #

Derivative operator for a function with specified argument type but automatically derived value type.

Examples

Expand
>>> :{
   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)]

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 Source #

Derivative operator for a function from any supported argument type to a scalar value.

Examples

Expand
>>> 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)

simpleDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> CT a Source #

Derivative for a scalar-to-scalar function.

Examples

Expand
>>> 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)

simpleValueAndDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> (b, CT a) Source #

Returns both the value and the derivative for a scalar-to-scalar function.

Examples

Expand
>>> 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))

customArgValDerivative :: (RevDiff (CT a) (CT a) a -> b) -> (c -> d) -> (b -> c) -> a -> d Source #

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

Expand
>>> :{
   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)]

Differentiable types

Tuple

twoArgsDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #

Differentiable operator for functions over two arguments and any supported by AutoDifferentiableValue value type. Equivalent to tupleArgDerivative up to the curring.

Examples

Expand
>>> 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)))

twoArgsDerivativeOverX :: (Additive (CT a0), AutoDifferentiableValue b) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #

Differentiable operator for functions over two arguments with respect to the first argument. Equivalent to tupleDerivativeOverX up to the curring.

Examples

Expand
>>> 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)

twoArgsDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #

Differentiable operator for functions over two arguments with respect to the second argument. Equivalent to tupleDerivativeOverY up to the curring.

tupleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) -> (a0, a1) -> DerivativeValue b Source #

Differentiable operator for functions over tuple argument with respect to the first argument.

Examples

Expand
>>> 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)

tupleDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) -> (a0, a1) -> DerivativeValue b Source #

Differentiable operator for functions over tuple argument with respect to the second argument.

Examples

Expand
>>> 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)

mkTupleArg :: (Additive b0, Additive b1) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a (b0, b1) (c0, c1) (d0, d1) Source #

Tuple argument descriptor builder. See this tutorial section for details and examples.

tupleArg :: (Additive b0, Additive b1) => RevDiff a (b0, b1) (c0, c1) -> (RevDiff a b0 c0, RevDiff a b1 c1) Source #

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

Expand
>>> 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)

tupleArgDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) -> (a0, a1) -> DerivativeValue b Source #

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

Expand
>>> 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)))

mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1) Source #

Tuple differentiable value builder See this tutorial section for details and examples.

tupleVal :: (Multiplicative b0, Multiplicative b1) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1) -> (a0, a1) Source #

Tuple differentiable value descriptor. See this tutorial section for details and examples.

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) Source #

Differentiable operator for functions with tuple value and any supported by AutoDifferentiableArgument argument type.

Examples

Expand
>>> 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)))

Triple

threeArgsToTriple :: Additive a => RevDiff a b0 c0 -> RevDiff a b1 c1 -> RevDiff a b2 c2 -> RevDiff a (b0, b1, b2) (c0, c1, c2) Source #

Transforms three RevDiff instances into a RevDiff instances of a triple. The inverese operation is tripleArg.

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 Source #

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.

derivative3ArgsOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b Source #

Differentiable operator for functions over three argument with respect to the first 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 Source #

Differentiable operator for functions over three argument with respect to the second 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 Source #

Differentiable operator for functions over three argument with respect to the third argument. and any supported by AutoDifferentiableValue value type.

tripleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #

Differentiable operator for functions over triple arguments with respect to the first argument.

tripleDerivativeOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #

Differentiable operator for functions over triple arguments with respect to the second argument.

tripleDerivativeOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #

Differentiable operator for functions over triple arguments with respect to the third argument.

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) Source #

Triple argument builder. See this tutorial section for details and examples for the tuple.

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) Source #

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

Expand
>>> 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)

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 Source #

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

Expand
>>> 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))

mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2) Source #

Triple differentiable value builder See this tutorial section for details and examples for tuple.

tripleVal :: (Multiplicative b0, Multiplicative b1, Multiplicative b2) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) -> (a0, a1, a2) Source #

Triple differentiable value descriptor. See this tutorial section for details and examples.

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) Source #

Differentiable operator for functions with tuple value and any supported by AutoDifferentiableArgument argument type.

Examples

Expand
>>> 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)

Boxed Vector

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) Source #

BoxedVector argument descriptor builder.

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) Source #

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

Expand
>>> 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]

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 Source #

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

Expand
>>> 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]]

mkBoxedVectorVal :: forall a b (n :: Nat). (a -> b) -> BoxedVector n a -> BoxedVector n b Source #

BoxedVector differentiable value builder See this tutorial section for details and examples.

boxedVectorVal :: forall b (n :: Nat) a c. Multiplicative b => BoxedVector n (RevDiff a b c) -> BoxedVector n a Source #

Boxed array differentiable value descriptor. See this tutorial section for details and examples.

Examples

Expand
>>> 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)]

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 Source #

Differentiable operator for functions with BoxedVector argument and any supported by AutoDifferentiableValue value type. The output is a BoxedVector instamce of corresponding drivatives.

Examples

Expand
>>> 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)]

Stream

mkStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (FiniteSupportStream b) (Stream c) -> Stream d Source #

Stream argument builder. See this tutorial section for details and examples for the tuple.

streamArg :: Additive b => RevDiff a (FiniteSupportStream b) (Stream c) -> Stream (RevDiff a b c) Source #

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

Expand
>>> 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,...

streamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (Stream (RevDiff' (Stream a) a) -> b) -> Stream a -> DerivativeValue b Source #

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

Expand
>>> 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,...,...

mkStreamVal :: (a -> b) -> Stream a -> Stream b Source #

Stream differentiable value builder See this tutorial section for details and examples.

streamVal :: Multiplicative b => Stream (RevDiff a b c) -> Stream a Source #

Stream value structure for differentiable functions.

Examples

Expand
>>> 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)]

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 Source #

Derivative operator for a function from any supported argument type to a Stream.

FiniteSupportStream

mkFiniteSupportStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream d Source #

Finite support stream argument descriptor builder. See this tutorial section for details and examples. It is expected that the argument function is linear or at least maps zero to zero.

finiteSupportStreamArg :: Additive b => RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream (RevDiff a b c) Source #

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

Expand
>>> 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]

finiteSupportStreamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) -> FiniteSupportStream a -> DerivativeValue b Source #

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 for the connection beetwen streams and finite support streams.

Examples

Expand
>>> 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]]

mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b Source #

Finite support stream differentiable value builder See this tutorial section for details and examples. It is expected that the argument function is linear or at least maps zero to zero.

finiteSupportStreamVal :: Multiplicative b => FiniteSupportStream (RevDiff a b c) -> FiniteSupportStream a Source #

Finite support stream value structure for differentiable functions.

Examples

Expand
>>> 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,...

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 Source #

Derivative operator for a function from any supported argument type to a FiniteSupportStream instance.

Examples

Expand
>>> 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,...

Maybe

maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c) Source #

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

Expand
>>> :{
 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

mkMaybeArg :: (RevDiff a b c -> d) -> RevDiff a (Maybe b) (Maybe c) -> Maybe d Source #

Maybe argument builder. Applies a function to Maybe value obtained from a RevDiff.

maybeArgDerivative :: AutoDifferentiableValue b => (Maybe (RevDiff' (Maybe a) a) -> b) -> Maybe a -> DerivativeValue b Source #

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

Expand
>>> 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

maybeVal :: Multiplicative b => Maybe (RevDiff a b c) -> Maybe a Source #

Maybe value structure for differentiable functions. Extracts the derivative with respect to the original function for Maybe types.

Examples

Expand
>>> :{
 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

mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b Source #

Maybe differentiable value builder. Creates a mapping function for Maybe types. See this tutorial section for details and examples.

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 Source #

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

Expand
>>> :{
 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