packages feed

backprop 0.1.5.2 → 0.2.0.0

raw patch · 21 files changed

+2552/−1147 lines, 21 filesdep +containersdep −binarydep −randomPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

Dependencies removed: binary, random

API changes (from Hackage documentation)

- Numeric.Backprop.Tuple: T0 :: T0
- Numeric.Backprop.Tuple: T2 :: !a -> !b -> T2 a b
- Numeric.Backprop.Tuple: T3 :: !a -> !b -> !c -> T3 a b c
- Numeric.Backprop.Tuple: [:&] :: !a -> !(T as) -> T (a : as)
- Numeric.Backprop.Tuple: [TNil] :: T '[]
- Numeric.Backprop.Tuple: constT :: forall c as. ListC (c <$> as) => (forall a. c a => a) -> Length as -> T as
- Numeric.Backprop.Tuple: curryT2 :: (T2 a b -> c) -> a -> b -> c
- Numeric.Backprop.Tuple: curryT3 :: (T3 a b c -> d) -> a -> b -> c -> d
- Numeric.Backprop.Tuple: data T :: [Type] -> Type
- Numeric.Backprop.Tuple: data T0
- Numeric.Backprop.Tuple: data T2 a b
- Numeric.Backprop.Tuple: data T3 a b c
- Numeric.Backprop.Tuple: indexT :: Index as a -> T as -> a
- Numeric.Backprop.Tuple: infixr 5 `tAppend`
- Numeric.Backprop.Tuple: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData b) => Control.DeepSeq.NFData (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData b, Control.DeepSeq.NFData c) => Control.DeepSeq.NFData (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Data.Binary.Class.Binary a, Data.Binary.Class.Binary b) => Data.Binary.Class.Binary (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (Data.Binary.Class.Binary a, Data.Binary.Class.Binary b, Data.Binary.Class.Binary c) => Data.Binary.Class.Binary (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Data.Data.Data b, Data.Data.Data a) => Data.Data.Data (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (Data.Data.Data c, Data.Data.Data b, Data.Data.Data a) => Data.Data.Data (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Data.Semigroup.Semigroup a, Data.Semigroup.Semigroup b) => Data.Semigroup.Semigroup (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (Data.Semigroup.Semigroup a, Data.Semigroup.Semigroup b, Data.Semigroup.Semigroup c) => Data.Semigroup.Semigroup (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Data.Semigroup.Semigroup a, Data.Semigroup.Semigroup b, Data.Semigroup.Semigroup c, GHC.Base.Monoid a, GHC.Base.Monoid b, GHC.Base.Monoid c) => GHC.Base.Monoid (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Data.Semigroup.Semigroup a, Data.Semigroup.Semigroup b, GHC.Base.Monoid a, GHC.Base.Monoid b) => GHC.Base.Monoid (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Classes.Eq c, GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Classes.Ord b, GHC.Classes.Ord a) => GHC.Classes.Ord (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Classes.Ord c, GHC.Classes.Ord b, GHC.Classes.Ord a) => GHC.Classes.Ord (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Float.Floating a, GHC.Float.Floating b) => GHC.Float.Floating (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Float.Floating a, GHC.Float.Floating b, GHC.Float.Floating c) => GHC.Float.Floating (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Num.Num a, GHC.Num.Num b) => GHC.Num.Num (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Num.Num a, GHC.Num.Num b, GHC.Num.Num c) => GHC.Num.Num (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Read.Read c, GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Real.Fractional a, GHC.Real.Fractional b) => GHC.Real.Fractional (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Real.Fractional a, GHC.Real.Fractional b, GHC.Real.Fractional c) => GHC.Real.Fractional (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (GHC.Show.Show c, GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (System.Random.Random a, System.Random.Random b) => System.Random.Random (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance (System.Random.Random a, System.Random.Random b, System.Random.Random c) => System.Random.Random (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint Data.Binary.Class.Binary as)) => Data.Binary.Class.Binary (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint Data.Semigroup.Semigroup as), Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Base.Monoid as)) => GHC.Base.Monoid (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Num.Num as)) => GHC.Num.Num (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Num.Num as), Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Real.Fractional as)) => GHC.Real.Fractional (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Num.Num as), Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Real.Fractional as), Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Float.Floating as)) => GHC.Float.Floating (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Class.Known.Known [*] (Data.Type.Length.Length *) as, Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint System.Random.Random as)) => System.Random.Random (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance (Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Classes.Eq as), Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Classes.Ord as)) => GHC.Classes.Ord (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance Control.DeepSeq.NFData Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance Data.Bifunctor.Bifunctor (Numeric.Backprop.Tuple.T3 a)
- Numeric.Backprop.Tuple: instance Data.Bifunctor.Bifunctor Numeric.Backprop.Tuple.T2
- Numeric.Backprop.Tuple: instance Data.Binary.Class.Binary Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance Data.Data.Data Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance Data.Semigroup.Semigroup Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Base.Functor (Numeric.Backprop.Tuple.T2 a)
- Numeric.Backprop.Tuple: instance GHC.Base.Functor (Numeric.Backprop.Tuple.T3 a b)
- Numeric.Backprop.Tuple: instance GHC.Base.Monoid Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Classes.Eq Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Classes.Ord Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Float.Floating Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Generics.Generic (Numeric.Backprop.Tuple.T2 a b)
- Numeric.Backprop.Tuple: instance GHC.Generics.Generic (Numeric.Backprop.Tuple.T3 a b c)
- Numeric.Backprop.Tuple: instance GHC.Generics.Generic Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Num.Num Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Read.Read Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Real.Fractional Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance GHC.Show.Show Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field1 (Numeric.Backprop.Tuple.T ((':) * a as)) (Numeric.Backprop.Tuple.T ((':) * a as)) a a
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field1 (Numeric.Backprop.Tuple.T2 a b) (Numeric.Backprop.Tuple.T2 a' b) a a'
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field1 (Numeric.Backprop.Tuple.T3 a b c) (Numeric.Backprop.Tuple.T3 a' b c) a a'
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field2 (Numeric.Backprop.Tuple.T ((':) * a ((':) * b as))) (Numeric.Backprop.Tuple.T ((':) * a ((':) * b as))) b b
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field2 (Numeric.Backprop.Tuple.T2 a b) (Numeric.Backprop.Tuple.T2 a b') b b'
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field2 (Numeric.Backprop.Tuple.T3 a b c) (Numeric.Backprop.Tuple.T3 a b' c) b b'
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field3 (Numeric.Backprop.Tuple.T ((':) * a ((':) * b ((':) * c as)))) (Numeric.Backprop.Tuple.T ((':) * a ((':) * b ((':) * c as)))) c c
- Numeric.Backprop.Tuple: instance Lens.Micro.Internal.Field3 (Numeric.Backprop.Tuple.T3 a b c) (Numeric.Backprop.Tuple.T3 a b c') c c'
- Numeric.Backprop.Tuple: instance System.Random.Random Numeric.Backprop.Tuple.T0
- Numeric.Backprop.Tuple: instance Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint Control.DeepSeq.NFData as) => Control.DeepSeq.NFData (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint Data.Semigroup.Semigroup as) => Data.Semigroup.Semigroup (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Classes.Eq as) => GHC.Classes.Eq (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: instance Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint GHC.Show.Show as) => GHC.Show.Show (Numeric.Backprop.Tuple.T as)
- Numeric.Backprop.Tuple: mapT :: forall c as. ListC (c <$> as) => (forall a. c a => a -> a) -> T as -> T as
- Numeric.Backprop.Tuple: onlyT :: a -> T '[a]
- Numeric.Backprop.Tuple: prodT :: Tuple as -> T as
- Numeric.Backprop.Tuple: t2Tup :: T2 a b -> (a, b)
- Numeric.Backprop.Tuple: t2_1 :: Lens (T2 a b) (T2 a' b) a a'
- Numeric.Backprop.Tuple: t2_2 :: Lens (T2 a b) (T2 a b') b b'
- Numeric.Backprop.Tuple: t3Tup :: T3 a b c -> (a, b, c)
- Numeric.Backprop.Tuple: t3_1 :: Lens (T3 a b c) (T3 a' b c) a a'
- Numeric.Backprop.Tuple: t3_2 :: Lens (T3 a b c) (T3 a b' c) b b'
- Numeric.Backprop.Tuple: t3_3 :: Lens (T3 a b c) (T3 a b c') c c'
- Numeric.Backprop.Tuple: tAppend :: T as -> T bs -> T (as ++ bs)
- Numeric.Backprop.Tuple: tDrop :: forall as bs cs. Length as -> Lens (T (as ++ bs)) (T (as ++ cs)) (T bs) (T cs)
- Numeric.Backprop.Tuple: tHead :: Lens (T (a : as)) (T (b : as)) a b
- Numeric.Backprop.Tuple: tIx :: Index as a -> Lens' (T as) a
- Numeric.Backprop.Tuple: tOnly :: T '[a] -> a
- Numeric.Backprop.Tuple: tProd :: T as -> Tuple as
- Numeric.Backprop.Tuple: tSplit :: Length as -> T (as ++ bs) -> (T as, T bs)
- Numeric.Backprop.Tuple: tTail :: Lens (T (a : as)) (T (a : bs)) (T as) (T bs)
- Numeric.Backprop.Tuple: tTake :: forall as bs cs. Length as -> Lens (T (as ++ bs)) (T (cs ++ bs)) (T as) (T cs)
- Numeric.Backprop.Tuple: tupT2 :: (a, b) -> T2 a b
- Numeric.Backprop.Tuple: tupT3 :: (a, b, c) -> T3 a b c
- Numeric.Backprop.Tuple: uncurryT2 :: (a -> b -> c) -> T2 a b -> c
- Numeric.Backprop.Tuple: uncurryT3 :: (a -> b -> c -> d) -> T3 a b c -> d
- Numeric.Backprop.Tuple: zipT :: forall c as. ListC (c <$> as) => (forall a. c a => a -> a -> a) -> T as -> T as -> T as
+ Numeric.Backprop: add :: (Backprop a, Generic a, GAdd (Rep a)) => a -> a -> a
+ Numeric.Backprop: auto :: a -> BVar s a
+ Numeric.Backprop: backpropWith :: Backprop a => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b -> b) -> (b, a)
+ Numeric.Backprop: backpropWith2 :: (Backprop a, Backprop b) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c -> c) -> (c, (a, b))
+ Numeric.Backprop: backpropWithN :: (Every Backprop as, Known Length as) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b -> b) -> (b, Tuple as)
+ Numeric.Backprop: class Backprop a
+ Numeric.Backprop: one :: (Backprop a, Generic a, GOne (Rep a)) => a -> a
+ Numeric.Backprop: zero :: (Backprop a, Generic a, GZero (Rep a)) => a -> a
+ Numeric.Backprop.Class: add :: (Backprop a, Generic a, GAdd (Rep a)) => a -> a -> a
+ Numeric.Backprop.Class: addAsList :: Backprop b => (a -> [b]) -> ([b] -> a) -> a -> a -> a
+ Numeric.Backprop.Class: addIsList :: (IsList a, Backprop (Item a)) => a -> a -> a
+ Numeric.Backprop.Class: addNum :: Num a => a -> a -> a
+ Numeric.Backprop.Class: addVec :: (Vector v a, Backprop a) => v a -> v a -> v a
+ Numeric.Backprop.Class: class Backprop a
+ Numeric.Backprop.Class: class GAdd f
+ Numeric.Backprop.Class: class GOne f
+ Numeric.Backprop.Class: class GZero f
+ Numeric.Backprop.Class: gadd :: GAdd f => f t -> f t -> f t
+ Numeric.Backprop.Class: genericAdd :: (Generic a, GAdd (Rep a)) => a -> a -> a
+ Numeric.Backprop.Class: genericOne :: (Generic a, GOne (Rep a)) => a -> a
+ Numeric.Backprop.Class: genericZero :: (Generic a, GZero (Rep a)) => a -> a
+ Numeric.Backprop.Class: gone :: GOne f => f t -> f t
+ Numeric.Backprop.Class: gzero :: GZero f => f t -> f t
+ Numeric.Backprop.Class: instance (Data.Primitive.Types.Prim a, Numeric.Backprop.Class.Backprop a) => Numeric.Backprop.Class.Backprop (Data.Vector.Primitive.Vector a)
+ Numeric.Backprop.Class: instance (Data.Vector.Unboxed.Base.Unbox a, Numeric.Backprop.Class.Backprop a) => Numeric.Backprop.Class.Backprop (Data.Vector.Unboxed.Base.Vector a)
+ Numeric.Backprop.Class: instance (Foreign.Storable.Storable a, Numeric.Backprop.Class.Backprop a) => Numeric.Backprop.Class.Backprop (Data.Vector.Storable.Vector a)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.Backprop a, GHC.Classes.Ord k) => Numeric.Backprop.Class.Backprop (Data.Map.Internal.Map k a)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.Backprop a, Numeric.Backprop.Class.Backprop b) => Numeric.Backprop.Class.Backprop (a, b)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.Backprop a, Numeric.Backprop.Class.Backprop b, Numeric.Backprop.Class.Backprop c) => Numeric.Backprop.Class.Backprop (a, b, c)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.Backprop a, Numeric.Backprop.Class.Backprop b, Numeric.Backprop.Class.Backprop c, Numeric.Backprop.Class.Backprop d) => Numeric.Backprop.Class.Backprop (a, b, c, d)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.Backprop a, Numeric.Backprop.Class.Backprop b, Numeric.Backprop.Class.Backprop c, Numeric.Backprop.Class.Backprop d, Numeric.Backprop.Class.Backprop e) => Numeric.Backprop.Class.Backprop (a, b, c, d, e)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.GAdd f, Numeric.Backprop.Class.GAdd g) => Numeric.Backprop.Class.GAdd ((GHC.Generics.:*:) * f g)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.GOne f, Numeric.Backprop.Class.GOne g) => Numeric.Backprop.Class.GOne ((GHC.Generics.:*:) * f g)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.GOne f, Numeric.Backprop.Class.GOne g) => Numeric.Backprop.Class.GOne ((GHC.Generics.:+:) * f g)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.GZero f, Numeric.Backprop.Class.GZero g) => Numeric.Backprop.Class.GZero ((GHC.Generics.:*:) * f g)
+ Numeric.Backprop.Class: instance (Numeric.Backprop.Class.GZero f, Numeric.Backprop.Class.GZero g) => Numeric.Backprop.Class.GZero ((GHC.Generics.:+:) * f g)
+ Numeric.Backprop.Class: instance GHC.Float.RealFloat a => Numeric.Backprop.Class.Backprop (Data.Complex.Complex a)
+ Numeric.Backprop.Class: instance GHC.Real.Integral a => Numeric.Backprop.Class.Backprop (GHC.Real.Ratio a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop ()
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop (Data.Proxy.Proxy * a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop Data.Void.Void
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop GHC.Integer.Type.Integer
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop GHC.Types.Double
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop GHC.Types.Float
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop GHC.Types.Int
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.Functor.Identity.Identity a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.IntMap.Internal.IntMap a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.List.NonEmpty.NonEmpty a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.Sequence.Internal.Seq a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.Type.Combinator.I a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (Data.Vector.Vector a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop (GHC.Base.Maybe a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.Backprop [a]
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.GAdd (GHC.Generics.K1 * i a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.GOne (GHC.Generics.K1 * i a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.Backprop a => Numeric.Backprop.Class.GZero (GHC.Generics.K1 * i a)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GAdd (GHC.Generics.U1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GAdd (GHC.Generics.V1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GAdd f => Numeric.Backprop.Class.GAdd ((GHC.Generics.:.:) * * f g)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GAdd f => Numeric.Backprop.Class.GAdd (GHC.Generics.M1 * i c f)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GOne (GHC.Generics.U1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GOne (GHC.Generics.V1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GOne f => Numeric.Backprop.Class.GOne ((GHC.Generics.:.:) * * f g)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GOne f => Numeric.Backprop.Class.GOne (GHC.Generics.M1 * i c f)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GZero (GHC.Generics.U1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GZero (GHC.Generics.V1 *)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GZero f => Numeric.Backprop.Class.GZero ((GHC.Generics.:.:) * * f g)
+ Numeric.Backprop.Class: instance Numeric.Backprop.Class.GZero f => Numeric.Backprop.Class.GZero (GHC.Generics.M1 * i c f)
+ Numeric.Backprop.Class: instance Type.Family.List.ListC ((Type.Family.List.<$>) * GHC.Types.Constraint Numeric.Backprop.Class.Backprop ((Type.Family.List.<$>) * * f as)) => Numeric.Backprop.Class.Backprop (Data.Type.Product.Prod * f as)
+ Numeric.Backprop.Class: instance Type.Family.Maybe.MaybeC ((Type.Family.Maybe.<$>) * GHC.Types.Constraint Numeric.Backprop.Class.Backprop ((Type.Family.Maybe.<$>) * * f a)) => Numeric.Backprop.Class.Backprop (Data.Type.Option.Option * f a)
+ Numeric.Backprop.Class: one :: (Backprop a, Generic a, GOne (Rep a)) => a -> a
+ Numeric.Backprop.Class: oneFunctor :: (Functor f, Backprop a) => f a -> f a
+ Numeric.Backprop.Class: oneNum :: Num a => a -> a
+ Numeric.Backprop.Class: oneVec :: (Vector v a, Backprop a) => v a -> v a
+ Numeric.Backprop.Class: zero :: (Backprop a, Generic a, GZero (Rep a)) => a -> a
+ Numeric.Backprop.Class: zeroFunctor :: (Functor f, Backprop a) => f a -> f a
+ Numeric.Backprop.Class: zeroNum :: Num a => a -> a
+ Numeric.Backprop.Class: zeroVec :: (Vector v a, Backprop a) => v a -> v a
+ Numeric.Backprop.Explicit: AF :: (a -> a -> a) -> AddFunc a
+ Numeric.Backprop.Explicit: I :: a -> I a
+ Numeric.Backprop.Explicit: OF :: (a -> a) -> OneFunc a
+ Numeric.Backprop.Explicit: Op :: (Tuple as -> (a, a -> Tuple as)) -> Op as a
+ Numeric.Backprop.Explicit: ZF :: (a -> a) -> ZeroFunc a
+ Numeric.Backprop.Explicit: [:<] :: Prod k f (:) k a1 as
+ Numeric.Backprop.Explicit: [getI] :: I a -> a
+ Numeric.Backprop.Explicit: [runAF] :: AddFunc a -> a -> a -> a
+ Numeric.Backprop.Explicit: [runOF] :: OneFunc a -> a -> a
+ Numeric.Backprop.Explicit: [runOpWith] :: Op as a -> Tuple as -> (a, a -> Tuple as)
+ Numeric.Backprop.Explicit: [runZF] :: ZeroFunc a -> a -> a
+ Numeric.Backprop.Explicit: [Ø] :: Prod k f [] k
+ Numeric.Backprop.Explicit: add :: (Backprop a, Generic a, GAdd (Rep a)) => a -> a -> a
+ Numeric.Backprop.Explicit: addFunc :: Backprop a => AddFunc a
+ Numeric.Backprop.Explicit: addFuncs :: (Every Backprop as, Known Length as) => Prod AddFunc as
+ Numeric.Backprop.Explicit: afNum :: Num a => AddFunc a
+ Numeric.Backprop.Explicit: afNums :: (Every Num as, Known Length as) => Prod AddFunc as
+ Numeric.Backprop.Explicit: auto :: a -> BVar s a
+ Numeric.Backprop.Explicit: backprop :: ZeroFunc a -> OneFunc b -> (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a)
+ Numeric.Backprop.Explicit: backprop2 :: ZeroFunc a -> ZeroFunc b -> OneFunc c -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c, (a, b))
+ Numeric.Backprop.Explicit: backpropN :: forall as b. () => Prod ZeroFunc as -> OneFunc b -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, Tuple as)
+ Numeric.Backprop.Explicit: backpropWith :: ZeroFunc a -> (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b -> b) -> (b, a)
+ Numeric.Backprop.Explicit: backpropWith2 :: ZeroFunc a -> ZeroFunc b -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c -> c) -> (c, (a, b))
+ Numeric.Backprop.Explicit: backpropWithN :: Prod ZeroFunc as -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b -> b) -> (b, Tuple as)
+ Numeric.Backprop.Explicit: class Backprop a
+ Numeric.Backprop.Explicit: class EveryC k c as => Every k (c :: k -> Constraint) (as :: [k])
+ Numeric.Backprop.Explicit: class Reifies k (s :: k) a | s -> a
+ Numeric.Backprop.Explicit: coerceVar :: Coercible a b => BVar s a -> BVar s b
+ Numeric.Backprop.Explicit: collectVar :: forall t a s. (Reifies s W, Foldable t, Functor t) => AddFunc a -> ZeroFunc a -> ZeroFunc (t a) -> t (BVar s a) -> BVar s (t a)
+ Numeric.Backprop.Explicit: constVar :: a -> BVar s a
+ Numeric.Backprop.Explicit: data Prod k (f :: k -> *) (a :: [k]) :: forall k. () => (k -> *) -> [k] -> *
+ Numeric.Backprop.Explicit: data BVar s a
+ Numeric.Backprop.Explicit: data W
+ Numeric.Backprop.Explicit: evalBP :: (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> b
+ Numeric.Backprop.Explicit: evalBP2 :: (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> c
+ Numeric.Backprop.Explicit: evalBPN :: forall as b. () => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> b
+ Numeric.Backprop.Explicit: gradBP :: ZeroFunc a -> OneFunc b -> (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> a
+ Numeric.Backprop.Explicit: gradBP2 :: ZeroFunc a -> ZeroFunc b -> OneFunc c -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (a, b)
+ Numeric.Backprop.Explicit: gradBPN :: Prod ZeroFunc as -> OneFunc b -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> Tuple as
+ Numeric.Backprop.Explicit: head' :: () => Prod k f (:<) k a as -> f a
+ Numeric.Backprop.Explicit: idOp :: Op '[a] a
+ Numeric.Backprop.Explicit: infix 6 :>
+ Numeric.Backprop.Explicit: infixr 5 ::<
+ Numeric.Backprop.Explicit: isoVar :: Reifies s W => AddFunc a -> ZeroFunc b -> (a -> b) -> (b -> a) -> BVar s a -> BVar s b
+ Numeric.Backprop.Explicit: isoVar2 :: Reifies s W => AddFunc a -> AddFunc b -> ZeroFunc c -> (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop.Explicit: isoVar3 :: Reifies s W => AddFunc a -> AddFunc b -> AddFunc c -> ZeroFunc d -> (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop.Explicit: isoVarN :: Reifies s W => Prod AddFunc as -> ZeroFunc b -> (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop.Explicit: liftOp :: forall as b s. Reifies s W => Prod AddFunc as -> ZeroFunc b -> Op as b -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop.Explicit: liftOp1 :: forall a b s. Reifies s W => AddFunc a -> ZeroFunc b -> Op '[a] b -> BVar s a -> BVar s b
+ Numeric.Backprop.Explicit: liftOp2 :: forall a b c s. Reifies s W => AddFunc a -> AddFunc b -> ZeroFunc c -> Op '[a, b] c -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop.Explicit: liftOp3 :: forall a b c d s. Reifies s W => AddFunc a -> AddFunc b -> AddFunc c -> ZeroFunc d -> Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop.Explicit: newtype AddFunc a
+ Numeric.Backprop.Explicit: newtype I a :: * -> *
+ Numeric.Backprop.Explicit: newtype OneFunc a
+ Numeric.Backprop.Explicit: newtype Op as a
+ Numeric.Backprop.Explicit: newtype ZeroFunc a
+ Numeric.Backprop.Explicit: noGrad :: (Tuple as -> b) -> Op as b
+ Numeric.Backprop.Explicit: noGrad1 :: (a -> b) -> Op '[a] b
+ Numeric.Backprop.Explicit: ofNum :: Num a => OneFunc a
+ Numeric.Backprop.Explicit: ofNums :: (Every Num as, Known Length as) => Prod OneFunc as
+ Numeric.Backprop.Explicit: one :: (Backprop a, Generic a, GOne (Rep a)) => a -> a
+ Numeric.Backprop.Explicit: oneFunc :: Backprop a => OneFunc a
+ Numeric.Backprop.Explicit: oneFuncs :: (Every Backprop as, Known Length as) => Prod OneFunc as
+ Numeric.Backprop.Explicit: only :: () => f a -> Prod k f (:) k a [] k
+ Numeric.Backprop.Explicit: only_ :: () => a -> Tuple (:) * a [] *
+ Numeric.Backprop.Explicit: op0 :: a -> Op '[] a
+ Numeric.Backprop.Explicit: op1 :: (a -> (b, b -> a)) -> Op '[a] b
+ Numeric.Backprop.Explicit: op2 :: (a -> b -> (c, c -> (a, b))) -> Op '[a, b] c
+ Numeric.Backprop.Explicit: op3 :: (a -> b -> c -> (d, d -> (a, b, c))) -> Op '[a, b, c] d
+ Numeric.Backprop.Explicit: opCoerce :: Coercible a b => Op '[a] b
+ Numeric.Backprop.Explicit: opConst :: (Every Num as, Known Length as) => a -> Op as a
+ Numeric.Backprop.Explicit: opConst' :: Every Num as => Length as -> a -> Op as a
+ Numeric.Backprop.Explicit: opIso :: (a -> b) -> (b -> a) -> Op '[a] b
+ Numeric.Backprop.Explicit: opIsoN :: (Tuple as -> b) -> (b -> Tuple as) -> Op as b
+ Numeric.Backprop.Explicit: opLens :: Num a => Lens' a b -> Op '[a] b
+ Numeric.Backprop.Explicit: opTup :: Op as (Tuple as)
+ Numeric.Backprop.Explicit: previewVar :: forall b a s. Reifies s W => AddFunc a -> ZeroFunc a -> Traversal' b a -> BVar s b -> Maybe (BVar s a)
+ Numeric.Backprop.Explicit: sequenceVar :: forall t a s. (Reifies s W, Traversable t) => AddFunc a -> ZeroFunc a -> BVar s (t a) -> t (BVar s a)
+ Numeric.Backprop.Explicit: setVar :: forall a b s. Reifies s W => AddFunc a -> AddFunc b -> ZeroFunc a -> ZeroFunc b -> Lens' b a -> BVar s a -> BVar s b -> BVar s b
+ Numeric.Backprop.Explicit: toListOfVar :: forall b a s. Reifies s W => AddFunc a -> ZeroFunc a -> Traversal' b a -> BVar s b -> [BVar s a]
+ Numeric.Backprop.Explicit: type Tuple = Prod * I
+ Numeric.Backprop.Explicit: viewVar :: forall a b s. Reifies s W => AddFunc a -> ZeroFunc a -> Lens' b a -> BVar s b -> BVar s a
+ Numeric.Backprop.Explicit: zero :: (Backprop a, Generic a, GZero (Rep a)) => a -> a
+ Numeric.Backprop.Explicit: zeroFunc :: Backprop a => ZeroFunc a
+ Numeric.Backprop.Explicit: zeroFuncs :: (Every Backprop as, Known Length as) => Prod ZeroFunc as
+ Numeric.Backprop.Explicit: zfNum :: Num a => ZeroFunc a
+ Numeric.Backprop.Explicit: zfNums :: (Every Num as, Known Length as) => Prod ZeroFunc as
+ Numeric.Backprop.Num: (.~~) :: forall a b s. (Reifies s W, Num a, Num b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
+ Numeric.Backprop.Num: (^^.) :: forall a b s. (Reifies s W, Num a) => BVar s b -> Lens' b a -> BVar s a
+ Numeric.Backprop.Num: (^^..) :: forall b a s. (Num a, Reifies s W) => BVar s b -> Traversal' b a -> [BVar s a]
+ Numeric.Backprop.Num: (^^?) :: forall b a s. (Num a, Reifies s W) => BVar s b -> Traversal' b a -> Maybe (BVar s a)
+ Numeric.Backprop.Num: I :: a -> I a
+ Numeric.Backprop.Num: Op :: (Tuple as -> (a, a -> Tuple as)) -> Op as a
+ Numeric.Backprop.Num: [:<] :: Prod k f (:) k a1 as
+ Numeric.Backprop.Num: [getI] :: I a -> a
+ Numeric.Backprop.Num: [runOpWith] :: Op as a -> Tuple as -> (a, a -> Tuple as)
+ Numeric.Backprop.Num: [Ø] :: Prod k f [] k
+ Numeric.Backprop.Num: auto :: a -> BVar s a
+ Numeric.Backprop.Num: backprop :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a)
+ Numeric.Backprop.Num: backprop2 :: (Num a, Num b, Num c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c, (a, b))
+ Numeric.Backprop.Num: backpropN :: (Every Num as, Known Length as, Num b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, Tuple as)
+ Numeric.Backprop.Num: backpropWith :: Num a => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b -> b) -> (b, a)
+ Numeric.Backprop.Num: backpropWith2 :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c -> c) -> (c, (a, b))
+ Numeric.Backprop.Num: backpropWithN :: (Every Num as, Known Length as) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b -> b) -> (b, Tuple as)
+ Numeric.Backprop.Num: class EveryC k c as => Every k (c :: k -> Constraint) (as :: [k])
+ Numeric.Backprop.Num: class Reifies k (s :: k) a | s -> a
+ Numeric.Backprop.Num: coerceVar :: Coercible a b => BVar s a -> BVar s b
+ Numeric.Backprop.Num: collectVar :: forall t a s. (Num a, Num (t a), Reifies s W, Foldable t, Functor t) => t (BVar s a) -> BVar s (t a)
+ Numeric.Backprop.Num: constVar :: a -> BVar s a
+ Numeric.Backprop.Num: data Prod k (f :: k -> *) (a :: [k]) :: forall k. () => (k -> *) -> [k] -> *
+ Numeric.Backprop.Num: data BVar s a
+ Numeric.Backprop.Num: data W
+ Numeric.Backprop.Num: evalBP :: (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> b
+ Numeric.Backprop.Num: evalBP2 :: (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> c
+ Numeric.Backprop.Num: evalBPN :: forall as b. () => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> b
+ Numeric.Backprop.Num: gradBP :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> a
+ Numeric.Backprop.Num: gradBP2 :: (Num a, Num b, Num c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (a, b)
+ Numeric.Backprop.Num: gradBPN :: (Every Num as, Known Length as, Num b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> Tuple as
+ Numeric.Backprop.Num: head' :: () => Prod k f (:<) k a as -> f a
+ Numeric.Backprop.Num: idOp :: Op '[a] a
+ Numeric.Backprop.Num: infix 6 :>
+ Numeric.Backprop.Num: infixl 8 .~~
+ Numeric.Backprop.Num: infixr 5 ::<
+ Numeric.Backprop.Num: isoVar :: (Num a, Num b, Reifies s W) => (a -> b) -> (b -> a) -> BVar s a -> BVar s b
+ Numeric.Backprop.Num: isoVar2 :: (Num a, Num b, Num c, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop.Num: isoVar3 :: (Num a, Num b, Num c, Num d, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop.Num: isoVarN :: (Every Num as, Known Length as, Num b, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop.Num: liftOp :: forall as b s. (Every Num as, Known Length as, Num b, Reifies s W) => Op as b -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop.Num: liftOp1 :: forall a b s. (Num a, Num b, Reifies s W) => Op '[a] b -> BVar s a -> BVar s b
+ Numeric.Backprop.Num: liftOp2 :: forall a b c s. (Num a, Num b, Num c, Reifies s W) => Op '[a, b] c -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop.Num: liftOp3 :: forall a b c d s. (Num a, Num b, Num c, Num d, Reifies s W) => Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop.Num: newtype I a :: * -> *
+ Numeric.Backprop.Num: newtype Op as a
+ Numeric.Backprop.Num: noGrad :: (Tuple as -> b) -> Op as b
+ Numeric.Backprop.Num: noGrad1 :: (a -> b) -> Op '[a] b
+ Numeric.Backprop.Num: only :: () => f a -> Prod k f (:) k a [] k
+ Numeric.Backprop.Num: only_ :: () => a -> Tuple (:) * a [] *
+ Numeric.Backprop.Num: op0 :: a -> Op '[] a
+ Numeric.Backprop.Num: op1 :: (a -> (b, b -> a)) -> Op '[a] b
+ Numeric.Backprop.Num: op2 :: (a -> b -> (c, c -> (a, b))) -> Op '[a, b] c
+ Numeric.Backprop.Num: op3 :: (a -> b -> c -> (d, d -> (a, b, c))) -> Op '[a, b, c] d
+ Numeric.Backprop.Num: opCoerce :: Coercible a b => Op '[a] b
+ Numeric.Backprop.Num: opConst :: (Every Num as, Known Length as) => a -> Op as a
+ Numeric.Backprop.Num: opConst' :: Every Num as => Length as -> a -> Op as a
+ Numeric.Backprop.Num: opIso :: (a -> b) -> (b -> a) -> Op '[a] b
+ Numeric.Backprop.Num: opIsoN :: (Tuple as -> b) -> (b -> Tuple as) -> Op as b
+ Numeric.Backprop.Num: opLens :: Num a => Lens' a b -> Op '[a] b
+ Numeric.Backprop.Num: opTup :: Op as (Tuple as)
+ Numeric.Backprop.Num: previewVar :: forall b a s. (Reifies s W, Num a) => Traversal' b a -> BVar s b -> Maybe (BVar s a)
+ Numeric.Backprop.Num: sequenceVar :: forall t a s. (Num a, Reifies s W, Traversable t) => BVar s (t a) -> t (BVar s a)
+ Numeric.Backprop.Num: setVar :: forall a b s. (Reifies s W, Num a, Num b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
+ Numeric.Backprop.Num: toListOfVar :: forall b a s. (Num a, Reifies s W) => Traversal' b a -> BVar s b -> [BVar s a]
+ Numeric.Backprop.Num: type Tuple = Prod * I
+ Numeric.Backprop.Num: viewVar :: forall a b s. (Reifies s W, Num a) => Lens' b a -> BVar s b -> BVar s a
+ Prelude.Backprop.Explicit: coerce :: forall a b s. Coercible a b => BVar s a -> BVar s b
+ Prelude.Backprop.Explicit: fmap :: forall f a b s. (Traversable f, Reifies s W) => AddFunc a -> AddFunc b -> ZeroFunc a -> ZeroFunc b -> ZeroFunc (f b) -> (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
+ Prelude.Backprop.Explicit: length :: forall t a b s. (Foldable t, Num b, Reifies s W) => AddFunc (t a) -> ZeroFunc (t a) -> ZeroFunc b -> BVar s (t a) -> BVar s b
+ Prelude.Backprop.Explicit: liftA2 :: forall f a b c s. (Traversable f, Applicative f, Reifies s W) => AddFunc a -> AddFunc b -> AddFunc c -> ZeroFunc a -> ZeroFunc b -> ZeroFunc c -> ZeroFunc (f c) -> (BVar s a -> BVar s b -> BVar s c) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c)
+ Prelude.Backprop.Explicit: liftA3 :: forall f a b c d s. (Traversable f, Applicative f, Reifies s W) => AddFunc a -> AddFunc b -> AddFunc c -> AddFunc d -> ZeroFunc a -> ZeroFunc b -> ZeroFunc c -> ZeroFunc d -> ZeroFunc (f d) -> (BVar s a -> BVar s b -> BVar s c -> BVar s d) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c) -> BVar s (f d)
+ Prelude.Backprop.Explicit: maximum :: forall t a s. (Foldable t, Functor t, Ord a, Reifies s W) => AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
+ Prelude.Backprop.Explicit: minimum :: forall t a s. (Foldable t, Functor t, Ord a, Reifies s W) => AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
+ Prelude.Backprop.Explicit: product :: forall t a s. (Foldable t, Functor t, Fractional a, Reifies s W) => AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
+ Prelude.Backprop.Explicit: pure :: forall t a s. (Foldable t, Applicative t, Reifies s W) => AddFunc a -> ZeroFunc a -> ZeroFunc (t a) -> BVar s a -> BVar s (t a)
+ Prelude.Backprop.Explicit: sum :: forall t a s. (Foldable t, Functor t, Num a, Reifies s W) => AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
+ Prelude.Backprop.Explicit: traverse :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Reifies s W) => AddFunc a -> AddFunc b -> AddFunc (t b) -> ZeroFunc a -> ZeroFunc b -> ZeroFunc (t b) -> ZeroFunc (f (t b)) -> (BVar s a -> f (BVar s b)) -> BVar s (t a) -> BVar s (f (t b))
+ Prelude.Backprop.Num: (<$>) :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
+ Prelude.Backprop.Num: coerce :: forall a b s. Coercible a b => BVar s a -> BVar s b
+ Prelude.Backprop.Num: fmap :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
+ Prelude.Backprop.Num: length :: forall t a b s. (Foldable t, Num (t a), Num b, Reifies s W) => BVar s (t a) -> BVar s b
+ Prelude.Backprop.Num: liftA2 :: forall f a b c s. (Traversable f, Applicative f, Num a, Num b, Num c, Num (f c), Reifies s W) => (BVar s a -> BVar s b -> BVar s c) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c)
+ Prelude.Backprop.Num: liftA3 :: forall f a b c d s. (Traversable f, Applicative f, Num a, Num b, Num c, Num d, Num (f d), Reifies s W) => (BVar s a -> BVar s b -> BVar s c -> BVar s d) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c) -> BVar s (f d)
+ Prelude.Backprop.Num: maximum :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop.Num: minimum :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop.Num: product :: forall t a s. (Foldable t, Functor t, Num (t a), Fractional a, Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop.Num: pure :: forall t a s. (Foldable t, Applicative t, Num (t a), Num a, Reifies s W) => BVar s a -> BVar s (t a)
+ Prelude.Backprop.Num: sum :: forall t a s. (Foldable t, Functor t, Num (t a), Num a, Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop.Num: traverse :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Num a, Num b, Num (f (t b)), Num (t b), Reifies s W) => (BVar s a -> f (BVar s b)) -> BVar s (t a) -> BVar s (f (t b))
- Numeric.Backprop: (.~~) :: forall a b s. (Reifies s W, Num a, Num b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
+ Numeric.Backprop: (.~~) :: forall a b s. (Reifies s W, Backprop a, Backprop b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
- Numeric.Backprop: (^^.) :: forall a b s. (Reifies s W, Num a) => BVar s b -> Lens' b a -> BVar s a
+ Numeric.Backprop: (^^.) :: forall a b s. (Reifies s W, Backprop a) => BVar s b -> Lens' b a -> BVar s a
- Numeric.Backprop: (^^..) :: forall b a s. (Num a, Reifies s W) => BVar s b -> Traversal' b a -> [BVar s a]
+ Numeric.Backprop: (^^..) :: forall b a s. (Backprop a, Reifies s W) => BVar s b -> Traversal' b a -> [BVar s a]
- Numeric.Backprop: (^^?) :: forall b a s. (Num a, Reifies s W) => BVar s b -> Traversal' b a -> Maybe (BVar s a)
+ Numeric.Backprop: (^^?) :: forall b a s. (Backprop a, Reifies s W) => BVar s b -> Traversal' b a -> Maybe (BVar s a)
- Numeric.Backprop: backprop :: forall a b. (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a)
+ Numeric.Backprop: backprop :: (Backprop a, Backprop b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a)
- Numeric.Backprop: backprop2 :: forall a b c. (Num a, Num b, Num c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c, (a, b))
+ Numeric.Backprop: backprop2 :: (Backprop a, Backprop b, Backprop c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c, (a, b))
- Numeric.Backprop: backpropN :: forall as b. (Every Num as, Num b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, Tuple as)
+ Numeric.Backprop: backpropN :: (Every Backprop as, Known Length as, Backprop b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, Tuple as)
- Numeric.Backprop: collectVar :: forall t a s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a) => t (BVar s a) -> BVar s (t a)
+ Numeric.Backprop: collectVar :: forall t a s. (Backprop a, Backprop (t a), Reifies s W, Foldable t, Functor t) => t (BVar s a) -> BVar s (t a)
- Numeric.Backprop: gradBP :: forall a b. (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> a
+ Numeric.Backprop: gradBP :: (Backprop a, Backprop b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> a
- Numeric.Backprop: gradBP2 :: (Num a, Num b, Num c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (a, b)
+ Numeric.Backprop: gradBP2 :: (Backprop a, Backprop b, Backprop c) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (a, b)
- Numeric.Backprop: gradBPN :: forall as b. (Every Num as, Num b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> Tuple as
+ Numeric.Backprop: gradBPN :: (Every Backprop as, Known Length as, Backprop b) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> Tuple as
- Numeric.Backprop: isoVar :: (Num a, Num b, Reifies s W) => (a -> b) -> (b -> a) -> BVar s a -> BVar s b
+ Numeric.Backprop: isoVar :: (Backprop a, Backprop b, Reifies s W) => (a -> b) -> (b -> a) -> BVar s a -> BVar s b
- Numeric.Backprop: isoVar2 :: (Num a, Num b, Num c, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop: isoVar2 :: (Backprop a, Backprop b, Backprop c, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
- Numeric.Backprop: isoVar3 :: (Num a, Num b, Num c, Num d, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop: isoVar3 :: (Backprop a, Backprop b, Backprop c, Backprop d, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
- Numeric.Backprop: isoVarN :: (Every Num as, Num b, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop: isoVarN :: (Every Backprop as, Known Length as, Backprop b, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
- Numeric.Backprop: liftOp :: forall as b s. (Reifies s W, Num b, Every Num as) => Op as b -> Prod (BVar s) as -> BVar s b
+ Numeric.Backprop: liftOp :: forall as b s. (Every Backprop as, Known Length as, Backprop b, Reifies s W) => Op as b -> Prod (BVar s) as -> BVar s b
- Numeric.Backprop: liftOp1 :: forall a b s. (Reifies s W, Num a, Num b) => Op '[a] b -> BVar s a -> BVar s b
+ Numeric.Backprop: liftOp1 :: forall a b s. (Backprop a, Backprop b, Reifies s W) => Op '[a] b -> BVar s a -> BVar s b
- Numeric.Backprop: liftOp2 :: forall a b c s. (Reifies s W, Num a, Num b, Num c) => Op '[a, b] c -> BVar s a -> BVar s b -> BVar s c
+ Numeric.Backprop: liftOp2 :: forall a b c s. (Backprop a, Backprop b, Backprop c, Reifies s W) => Op '[a, b] c -> BVar s a -> BVar s b -> BVar s c
- Numeric.Backprop: liftOp3 :: forall a b c d s. (Reifies s W, Num a, Num b, Num c, Num d) => Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d
+ Numeric.Backprop: liftOp3 :: forall a b c d s. (Backprop a, Backprop b, Backprop c, Backprop d, Reifies s W) => Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d
- Numeric.Backprop: previewVar :: forall b a s. (Num a, Reifies s W) => Traversal' b a -> BVar s b -> Maybe (BVar s a)
+ Numeric.Backprop: previewVar :: forall b a s. (Reifies s W, Backprop a) => Traversal' b a -> BVar s b -> Maybe (BVar s a)
- Numeric.Backprop: sequenceVar :: forall t a s. (Reifies s W, Traversable t, Num a) => BVar s (t a) -> t (BVar s a)
+ Numeric.Backprop: sequenceVar :: forall t a s. (Backprop a, Reifies s W, Traversable t) => BVar s (t a) -> t (BVar s a)
- Numeric.Backprop: setVar :: forall a b s. (Reifies s W, Num a, Num b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
+ Numeric.Backprop: setVar :: forall a b s. (Reifies s W, Backprop a, Backprop b) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
- Numeric.Backprop: toListOfVar :: forall b a s. (Num a, Reifies s W) => Traversal' b a -> BVar s b -> [BVar s a]
+ Numeric.Backprop: toListOfVar :: forall b a s. (Backprop a, Reifies s W) => Traversal' b a -> BVar s b -> [BVar s a]
- Numeric.Backprop: viewVar :: forall a b s. (Reifies s W, Num a) => Lens' b a -> BVar s b -> BVar s a
+ Numeric.Backprop: viewVar :: forall a b s. (Reifies s W, Backprop a) => Lens' b a -> BVar s b -> BVar s a
- Prelude.Backprop: (<$>) :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
+ Prelude.Backprop: (<$>) :: forall f a b s. (Traversable f, Backprop a, Backprop b, Backprop (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
- Prelude.Backprop: coerce :: forall a b s. (Coercible a b, Num a, Num b, Reifies s W) => BVar s a -> BVar s b
+ Prelude.Backprop: coerce :: forall a b s. Coercible a b => BVar s a -> BVar s b
- Prelude.Backprop: fmap :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
+ Prelude.Backprop: fmap :: forall f a b s. (Traversable f, Backprop a, Backprop b, Backprop (f b), Reifies s W) => (BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
- Prelude.Backprop: length :: forall t a b s. (Foldable t, Num (t a), Num b, Reifies s W) => BVar s (t a) -> BVar s b
+ Prelude.Backprop: length :: forall t a b s. (Foldable t, Backprop (t a), Backprop b, Num b, Reifies s W) => BVar s (t a) -> BVar s b
- Prelude.Backprop: liftA2 :: forall f a b c s. (Traversable f, Applicative f, Num a, Num b, Num c, Num (f c), Reifies s W) => (BVar s a -> BVar s b -> BVar s c) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c)
+ Prelude.Backprop: liftA2 :: forall f a b c s. (Traversable f, Applicative f, Backprop a, Backprop b, Backprop c, Backprop (f c), Reifies s W) => (BVar s a -> BVar s b -> BVar s c) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c)
- Prelude.Backprop: liftA3 :: forall f a b c d s. (Traversable f, Applicative f, Num a, Num b, Num c, Num d, Num (f d), Reifies s W) => (BVar s a -> BVar s b -> BVar s c -> BVar s d) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c) -> BVar s (f d)
+ Prelude.Backprop: liftA3 :: forall f a b c d s. (Traversable f, Applicative f, Backprop a, Backprop b, Backprop c, Backprop d, Backprop (f d), Reifies s W) => (BVar s a -> BVar s b -> BVar s c -> BVar s d) -> BVar s (f a) -> BVar s (f b) -> BVar s (f c) -> BVar s (f d)
- Prelude.Backprop: maximum :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop: maximum :: forall t a s. (Foldable t, Functor t, Backprop a, Ord a, Backprop (t a), Reifies s W) => BVar s (t a) -> BVar s a
- Prelude.Backprop: minimum :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop: minimum :: forall t a s. (Foldable t, Functor t, Backprop a, Ord a, Backprop (t a), Reifies s W) => BVar s (t a) -> BVar s a
- Prelude.Backprop: product :: forall t a s. (Foldable t, Functor t, Num (t a), Fractional a, Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop: product :: forall t a s. (Foldable t, Functor t, Backprop (t a), Backprop a, Fractional a, Reifies s W) => BVar s (t a) -> BVar s a
- Prelude.Backprop: pure :: forall t a s. (Foldable t, Applicative t, Num (t a), Num a, Reifies s W) => BVar s a -> BVar s (t a)
+ Prelude.Backprop: pure :: forall t a s. (Foldable t, Applicative t, Backprop (t a), Backprop a, Reifies s W) => BVar s a -> BVar s (t a)
- Prelude.Backprop: sum :: forall t a s. (Foldable t, Functor t, Num (t a), Num a, Reifies s W) => BVar s (t a) -> BVar s a
+ Prelude.Backprop: sum :: forall t a s. (Foldable t, Functor t, Backprop (t a), Backprop a, Num a, Reifies s W) => BVar s (t a) -> BVar s a
- Prelude.Backprop: traverse :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Num a, Num b, Num (f (t b)), Num (t b), Reifies s W) => (BVar s a -> f (BVar s b)) -> BVar s (t a) -> BVar s (f (t b))
+ Prelude.Backprop: traverse :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Backprop a, Backprop b, Backprop (f (t b)), Backprop (t b), Reifies s W) => (BVar s a -> f (BVar s b)) -> BVar s (t a) -> BVar s (f (t b))

Files

CHANGELOG.md view
@@ -1,6 +1,36 @@ Changelog ========= +Version 0.2.0.0+---------------++*May 1, 2018*++<https://github.com/mstksg/backprop/releases/tag/v0.2.0.0>++*   Added `Backprop` class in *Numeric.Backprop.Class*, which is a typeclass+    specifically for "backpropagatable" values.  This will replace `Num`.+*   API of *Numeric.Backprop* completely re-written to require values be+    instances of `Backprop` instead of `Num`.  This closes some outstanding+    issues with the reliance of `Num`, and allows backpropagation to work with+    non-Num instances like variable-length vectors, matrices, lists, tuples,+    etc. (including types from *accelerate*)+*   *Numeric.Backprop.Num* and *Prelude.Backprop.Num* modules added, providing+    the old interface that uses `Num` instances instead of `Backprop`+    instances, for those who wish to avoid writing orphan instances when+    working with external types.+*   *Numeric.Backprop.Explicit* and *Prelude.Backprop.Explicit* modules added,+    providing an interface that allows users to manually specify how zeroing,+    addition, and one-ing works on a per-value basis.  Useful for those who+    wish to avoid writing orphan instances of `Backprop` for types with no+    `Num` instances, or if you are mixing and matching styles.+*   `backpropWith` variants added, allowing you to specify a "final gradient",+    instead of assuming it to be 1.+*   Added `auto`, a shorter alias for `constVar` inspired by the *ad* library.+*   *Numeric.Backprop.Tuple* module removed.  I couldn't find a significant+    reason to keep it now that `Num` is no longer required for backpropagation.++ Version 0.1.5.2 --------------- 
README.md view
@@ -246,53 +246,6 @@  2.  Write tests! -3.  Explore potentially ditching `Num` for another typeclass that only has `+`,-    `0`, and `1`.  Currently, `Num` is required for all backpropagated types,-    but only `+`, `fromInteger 0`, and `fromInteger 1` are ever used.--    The main upside to using `Num` is that it integrates well with the rest of-    the Haskell ecosystem, and many things already have useful `Num` instances.--    There are two downsides -- one minor and one major.--    *   It requires more work to make a type backpropagatable.  Instead of-        writing only `+`, `0` and `1`, users must also define `*`, `-` or-        `negate`, `abs`, `signum`, and all of `fromInteger`.  However, I don't-        see this being a big issue in practice, since most values that will be-        used with *backprop* would presumably also benefit from having a full-        `Num` instance even without the need to backprop.--    *   Automatically generated prisms (used with `^^?`) work with tuples, and-        so cannot work out-of-the-box without a `Num` instance for tuples.  In-        addition, it's often useful to have anonymous products and tuples in-        general.--        This is bandaided-over by having *backprop* provide canonical-        tuple-with-`Num` types for different libraries to use, but it's not a-        perfect solution.--        This can be resolved by using the orphan instances in the-        *[NumInstances][]* package.  Still, there might be some headache for-        application developers if different libraries using *backprop*-        accidentally pull in their orphan instances from different places.--        [NumInstances]: https://hackage.haskell.org/package/NumInstances--        Alternatively, one day we can get `Num` instances for tuples into-        *base*!--    The extra complexity that would come from adding a custom typeclass just-    for `+` / `0` / `1`, though, I feel, might not be worth the benefit.  The-    entire numeric Haskell ecosystem, at the time, revolves around `Num`.--    However, it is worth noting that it wouldn't be too hard to add "Additive-    Typeclass" instances for any custom types -- one would just need to define-    `(<+>) = (+)`, `zero = fromInteger 0`, and `one = fromInteger 1` (a-    three-liner), so it might not be too bad.--    But really, a lot of this would all resolve itself if we got `Num`-    instances for tuples in base :)- 3.  Explore opportunities for parallelization.  There are some naive ways of     directly parallelizing right now, but potential overhead should be     investigated.
backprop.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 1a3823df38b9b0fe0ecb1481bea9f4b591e24a0abe5f96c21bf88c2b6055851b+-- hash: 0ba2801ba9787e38a25a6b3a1f48172558ed7066726034c01b1f3b01b9ee17fa  name:           backprop-version:        0.1.5.2+version:        0.2.0.0 synopsis:       Heterogeneous automatic differentation (backpropagation) description:    Write your functions to compute your result, and the library will                 automatically generate functions to compute your gradient.@@ -47,20 +47,23 @@   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints -fprint-explicit-kinds   build-depends:       base >=4.7 && <5-    , binary+    , containers     , deepseq     , microlens     , primitive-    , random     , reflection     , transformers     , type-combinators     , vector   exposed-modules:       Numeric.Backprop+      Numeric.Backprop.Class+      Numeric.Backprop.Explicit+      Numeric.Backprop.Num       Numeric.Backprop.Op-      Numeric.Backprop.Tuple       Prelude.Backprop+      Prelude.Backprop.Explicit+      Prelude.Backprop.Num   other-modules:       Numeric.Backprop.Internal       Data.Type.Util
bench/bench.hs view
@@ -25,6 +25,7 @@ import           GHC.Generics                 (Generic) import           GHC.TypeLits import           Numeric.Backprop+import           Numeric.Backprop.Class import           Numeric.LinearAlgebra.Static import           System.Directory import qualified Data.Vector.Generic          as VG@@ -314,21 +315,15 @@     uniform g = Net <$> MWC.uniform g <*> MWC.uniform g <*> MWC.uniform g     uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g -instance (Num a, Num b) => Num (a, b) where-    (x1,y1) + (x2,y2) = (x1 + x2, y1 + y2)-    (x1,y1) * (x2,y2) = (x1 * x2, y1 * y2)-    (x1,y1) - (x2,y2) = (x1 - x2, y1 - y2)-    abs (x, y)        = (abs x, abs y)-    signum (x, y)     = (signum x, signum y)-    fromInteger x     = (fromInteger x, fromInteger x)+instance Backprop (R n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum --- softMaxCrossEntropy---     :: KnownNat n---     => R n---     -> BPOpI s '[ R n ] Double--- softMaxCrossEntropy targ (r :< Ø) =  realToFrac tsum * log (vsum .$ (r :< Ø))---                                        - (dot .$ (r :< t :< Ø))---   where---     tsum = HM.sumElements . extract $ targ---     t    = constVar targ+instance (KnownNat n, KnownNat m) => Backprop (L m n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum +instance (KnownNat i, KnownNat o) => Backprop (Layer i o)+instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Backprop (Network i h1 h2 o)
renders/backprop-mnist.md view
@@ -67,6 +67,7 @@ import           GHC.Generics                        (Generic) import           GHC.TypeLits import           Numeric.Backprop+import           Numeric.Backprop.Class import           Numeric.LinearAlgebra.Static import           Numeric.OneLiner import           Text.Printf@@ -206,6 +207,15 @@ refer to the numbers in its type and use it to go about its normal hmatrixy business. +Now we need instances of `Backprop` for our types in order to use them+for automatic differentiation. Luckily, these can be generated+automatically using GHC Generics:++``` {.sourceCode .literate .haskell}+instance (KnownNat i, KnownNat o) => Backprop (Layer i o)+instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Backprop (Network i h1 h2 o)+```+ Ops === @@ -688,4 +698,21 @@       => MWC.Variate (Network i h1 h2 o) where     uniform g = Net <$> MWC.uniform g <*> MWC.uniform g <*> MWC.uniform g     uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g+```++Also, some orphan instances of `Backprop` for vector and matrix types.+These are provided by the [hmatrix-backprop] library normally:++  [hmatrix-backprop]: http://hackage.haskell.org/package/hmatrix-backprop++``` {.sourceCode .literate .haskell}+instance Backprop (R n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum++instance (KnownNat n, KnownNat m) => Backprop (L m n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum ```
renders/backprop-mnist.pdf view

binary file changed (133763 → 134752 bytes)

renders/extensible-neural.md view
@@ -62,6 +62,7 @@ import           Data.Tuple import           GHC.Generics                    (Generic) import           Numeric.Backprop+import           Numeric.Backprop.Class import           Numeric.LinearAlgebra.Static import           Numeric.OneLiner import           Text.Printf@@ -436,7 +437,9 @@     recip        = gRecip     fromRational = gFromRational +instance (KnownNat i, KnownNat o) => Backprop (Layer i o) + liftNet0     :: forall i hs o. (KnownNat i, KnownNat o)     => (forall m n. (KnownNat m, KnownNat n) => Layer m n)@@ -518,6 +521,11 @@     recip          = liftNet1 negate sing     fromRational x = liftNet0 (fromRational x) sing +instance (KnownNat i, KnownNat o, SingI hs) => Backprop (Net i hs o) where+    zero = liftNet1 zero sing+    add  = liftNet2 add sing+    one  = liftNet1 one sing+ instance KnownNat n => MWC.Variate (R n) where     uniform g = randomVector <$> MWC.uniform g <*> pure Uniform     uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g@@ -548,4 +556,14 @@     rnf = \case       NO l    -> rnf l       x :~ xs -> rnf x `seq` rnf xs++instance Backprop (R n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum++instance (KnownNat n, KnownNat m) => Backprop (L m n) where+    zero = zeroNum+    add  = addNum+    one  = oneNum ```
renders/extensible-neural.pdf view

binary file changed (107850 → 107912 bytes)

samples/backprop-mnist.lhs view
@@ -63,6 +63,7 @@ > import           GHC.Generics                        (Generic) > import           GHC.TypeLits > import           Numeric.Backprop+> import           Numeric.Backprop.Class > import           Numeric.LinearAlgebra.Static > import           Numeric.OneLiner > import           Text.Printf@@ -192,6 +193,13 @@ to the numbers in its type and use it to go about its normal hmatrixy business. +Now we need instances of `Backprop` for our types in order to use them for+automatic differentiation.  Luckily, these can be generated automatically+using GHC Generics:++> instance (KnownNat i, KnownNat o) => Backprop (Layer i o)+> instance (KnownNat i, KnownNat h1, KnownNat h2, KnownNat o) => Backprop (Network i h1 h2 o)+ Ops === @@ -626,3 +634,17 @@ >     uniform g = Net <$> MWC.uniform g <*> MWC.uniform g <*> MWC.uniform g >     uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g +Also, some orphan instances of `Backprop` for vector and matrix types.  These+are provided by the [hmatrix-backprop][] library normally:++> instance Backprop (R n) where+>     zero = zeroNum+>     add  = addNum+>     one  = oneNum+>+> instance (KnownNat n, KnownNat m) => Backprop (L m n) where+>     zero = zeroNum+>     add  = addNum+>     one  = oneNum++[hmatrix-backprop]: http://hackage.haskell.org/package/hmatrix-backprop
samples/extensible-neural.lhs view
@@ -59,6 +59,7 @@ > import           Data.Tuple > import           GHC.Generics                    (Generic) > import           Numeric.Backprop+> import           Numeric.Backprop.Class > import           Numeric.LinearAlgebra.Static > import           Numeric.OneLiner > import           Text.Printf@@ -414,7 +415,9 @@ >     recip        = gRecip >     fromRational = gFromRational >+> instance (KnownNat i, KnownNat o) => Backprop (Layer i o) >+> > liftNet0 >     :: forall i hs o. (KnownNat i, KnownNat o) >     => (forall m n. (KnownNat m, KnownNat n) => Layer m n)@@ -496,6 +499,11 @@ >     recip          = liftNet1 negate sing >     fromRational x = liftNet0 (fromRational x) sing >+> instance (KnownNat i, KnownNat o, SingI hs) => Backprop (Net i hs o) where+>     zero = liftNet1 zero sing+>     add  = liftNet2 add sing+>     one  = liftNet1 one sing+> > instance KnownNat n => MWC.Variate (R n) where >     uniform g = randomVector <$> MWC.uniform g <*> pure Uniform >     uniformR (l, h) g = (\x -> x * (h - l) + l) <$> MWC.uniform g@@ -526,3 +534,15 @@ >     rnf = \case >       NO l    -> rnf l >       x :~ xs -> rnf x `seq` rnf xs+>+> instance Backprop (R n) where+>     zero = zeroNum+>     add  = addNum+>     one  = oneNum+>+> instance (KnownNat n, KnownNat m) => Backprop (L m n) where+>     zero = zeroNum+>     add  = addNum+>     one  = oneNum++[hmatrix-backprop]: http://hackage.haskell.org/package/hmatrix-backprop
src/Data/Type/Util.hs view
@@ -11,11 +11,13 @@   , unzipP   , zipP   , zipWithPM_+  , zipWithPM3_   , vecToProd   , vecLen   , lengthProd   , listToVecDef   , fillProd+  , zipVecList   ) where  import           Data.Bifunctor@@ -66,6 +68,23 @@       x :< xs -> \case         y :< ys -> f x y *> go xs ys +zipWithPM3_+    :: forall m f g h as. Applicative m+    => (forall a. f a -> g a -> h a -> m ())+    -> Prod f as+    -> Prod g as+    -> Prod h as+    -> m ()+zipWithPM3_ f = go+  where+    go :: forall bs. Prod f bs -> Prod g bs -> Prod h bs -> m ()+    go = \case+      Ø -> \case+        Ø -> \case+          Ø -> pure ()+      x :< xs -> \case+        y :< ys -> \case+          z :< zs -> f x y z *> go xs ys zs  zipP     :: Prod f as@@ -122,3 +141,18 @@       x :< xs -> \case         []   -> Nothing         y:ys -> (f x y :<) <$> go xs ys++zipVecList+    :: forall a b c f g n. ()+    => (f a -> Maybe b -> g c)+    -> VecT n f a+    -> [b]+    -> VecT n g c+zipVecList f = go+  where+    go :: VecT m f a -> [b] -> VecT m g c+    go = \case+      ØV -> const ØV+      x :* xs -> \case+        []   -> f x Nothing  :* go xs []+        y:ys -> f x (Just y) :* go xs ys
src/Numeric/Backprop.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs            #-}-{-# LANGUAGE PatternSynonyms  #-}-{-# LANGUAGE RankNTypes       #-}+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE GADTs             #-}+{-# LANGUAGE PatternSynonyms   #-}+{-# LANGUAGE RankNTypes        #-}  -- | -- Module      : Numeric.Backprop@@ -46,17 +47,28 @@ -- and links to demonstrations and tutorials, or dive striaght in by -- reading the docs for 'BVar'. --+-- In the original version 0.1, this module required 'Num' instances for+-- methods instead of 'Backprop' instances.  This interface is still+-- available in "Numeric.Backprop.Num", which has the same API as this+-- module, except with 'Num' constraints on all values instead of+-- 'Backprop' constraints.+--+-- See "Prelude.Backprop.Explicit" for a version allowing you to provide+-- 'zero', 'add', and 'one' explicitly, which can be useful when attempting+-- to avoid orphan instances or when mixing both 'Backprop' and 'Num'+-- styles.+--  module Numeric.Backprop (     -- * Types-    BVar, W+    BVar, W, Backprop(..)     -- * Running-  , backprop, evalBP, gradBP+  , backprop, E.evalBP, gradBP, backpropWith     -- ** Multiple inputs-  , backprop2, evalBP2, gradBP2-  , backpropN, evalBPN, gradBPN, Every+  , backprop2, E.evalBP2, gradBP2, backpropWith2+  , backpropN, E.evalBPN, gradBPN, backpropWithN, Every     -- * Manipulating 'BVar'-  , constVar, coerceVar+  , E.constVar, E.auto, E.coerceVar   , (^^.), (.~~), (^^?), (^^..)   , viewVar, setVar   , sequenceVar, collectVar@@ -87,12 +99,15 @@   , Reifies   ) where -import           Data.Bifunctor import           Data.Reflection import           Data.Type.Index+import           Data.Type.Length import           Lens.Micro-import           Numeric.Backprop.Internal+import           Numeric.Backprop.Class+import           Numeric.Backprop.Explicit (BVar, W) import           Numeric.Backprop.Op+import           Type.Class.Known+import qualified Numeric.Backprop.Explicit as E  -- $liftops --@@ -138,6 +153,51 @@ -- -> b@, using 'evalBP', and this carries virtually zero overhead, so some -- libraries might even provide 'BVar' versions by default. +-- | 'backprop' generalized to multiple inputs of different types.  See the+-- "Numeric.Backprop.Op#prod" for a mini-tutorial on heterogeneous lists.+--+-- Not strictly necessary, because you can always uncurry a function by+-- passing in all of the inputs in a data type containing all of the+-- arguments or a giant tuple.  However, this could potentially also be+-- more performant.+--+-- A @'Prod' ('BVar' s) '[Double, Float, Double]@, for instance, is a tuple+-- of @'BVar' s 'Double'@, @'BVar' s 'Float'@, and @'BVar' s 'Double'@, and+-- can be pattern matched on using ':<' (cons) and 'Ø' (nil).+--+-- Tuples can be built and pattern matched on using '::<' (cons) and 'Ø'+-- (nil), as well.+--+-- The @'Every' 'Backprop' as@ in the constraint says that every value in+-- the type-level list @as@ must have a 'Backprop' instance.  This means+-- you can use, say, @'[Double, Float, Int]@, but not @'[Double, Bool,+-- String]@.+--+-- If you stick to /concerete/, monomorphic usage of this (with specific+-- types, typed into source code, known at compile-time), then @'Every'+-- 'Backprop' as@ should be fulfilled automatically.+backpropN+    :: (Every Backprop as, Known Length as, Backprop b)+    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> (b, Tuple as)+backpropN = E.backpropN E.zeroFuncs E.oneFunc+{-# INLINE backpropN #-}++-- | 'backpropN', but allows you to provide the gradient of the "final+-- result" with respect to the output of your function.  See 'backpropWith'+-- for more details.+--+-- @since 0.2.0.0+backpropWithN+    :: (Every Backprop as, Known Length as)+    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, Tuple as)+backpropWithN = E.backpropWithN E.zeroFuncs+{-# INLINE backpropWithN #-}+ -- | Turn a function @'BVar' s a -> 'BVar' s b@ into the function @a -> b@ -- that it represents, also computing its gradient @a@ as well. --@@ -145,55 +205,37 @@ -- that 'BVar's do not leak out of the context (similar to how it is used -- in "Control.Monad.ST"), and also as a reference to an ephemeral Wengert -- tape used to track the graph of references.------ Note that every type involved has to be an instance of 'Num'.  This is--- because gradients all need to be "summable" (which is implemented using--- 'sum' and '+'), and we also need to able to generate gradients of 1--- and 0.  Really, only '+' and 'fromInteger' methods are used from the--- 'Num' typeclass.------ This might change in the future, to allow easier integration with tuples--- (which typically do not have a 'Num' instance), and potentially make--- types easier to use (by only requiring '+', 0, and 1, and not the rest--- of the 'Num' class).------ See the <https://github.com/mstksg/backprop README> for a more detailed--- discussion on this issue.------ If you need a 'Num' instance for tuples, you can use the canonical 2---- and 3-tuples for the library in "Numeric.Backprop.Tuple".  If you need--- one for larger tuples, consider making a custom product type instead--- (making Num instances with something like--- <https://hackage.haskell.org/package/one-liner-instances one-liner-instances>).--- You can also use the orphan instances in the--- <https://hackage.haskell.org/package/NumInstances NumInstances> package--- (in particular, "Data.NumInstances.Tuple") if you are writing an--- application and do not have to worry about orphan instances. backprop-    :: forall a b. (Num a, Num b)+    :: (Backprop a, Backprop b)     => (forall s. Reifies s W => BVar s a -> BVar s b)     -> a     -> (b, a)-backprop f = second (getI . head')-           . backpropN (f . head')-           . only_+backprop = E.backprop E.zeroFunc E.oneFunc {-# INLINE backprop #-} --- | Turn a function @'BVar' s a -> 'BVar' s b@ into the function @a -> b@--- that it represents.+-- | A version of 'backprop' that allows you to specify the gradent of your+-- "final result" in with respect to the output of your function. ----- Benchmarks show that this should have virtually no overhead over--- directly writing a @a -> b@. 'BVar' is, in this situation, a zero-cost--- abstraction, performance-wise.+-- Typically, this is just the scalar 1, or a value of components that are+-- all 1. ----- Has a nice advantage over using 'backprop' in that it doesn't require--- 'Num' constraints on the input and output.+-- Instead of taking the @b@ gradient, the you may provide a @b -> b@,+-- which 'backpropWith' calls with the result of your function as the+-- argument.  This allows you to return something with the correct "shape",+-- if not a scalar. ----- See documentation of 'backprop' for more information.+-- 'backprop' is essentially 'backpropWith' with @'const' 1@ for scalars+-- and 'Num' instances. ---evalBP :: (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> b-evalBP f = evalBPN (f . head') . only_-{-# INLINE evalBP #-}+-- @since 0.2.0.0+backpropWith+    :: Backprop a+    => (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, a)+backpropWith = E.backpropWith E.zeroFunc+{-# INLINE backpropWith #-}  -- | Take a function @'BVar' s a -> 'BVar' s b@, interpreted as a function -- @a -> b@, and compute its gradient with respect to its input.@@ -207,58 +249,65 @@ -- -- See documentation of 'backprop' for more information. --+-- If you want to provide an explicit "final gradient" for the end, see+-- 'backpropWith'. gradBP-    :: forall a b. (Num a, Num b)+    :: (Backprop a, Backprop b)     => (forall s. Reifies s W => BVar s a -> BVar s b)     -> a     -> a-gradBP f = snd . backprop f+gradBP = E.gradBP E.zeroFunc E.oneFunc {-# INLINE gradBP #-}  -- | 'gradBP' generalized to multiple inputs of different types.  See -- documentation for 'backpropN' for more details. gradBPN-    :: forall as b. (Every Num as, Num b)+    :: (Every Backprop as, Known Length as, Backprop b)     => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)     -> Tuple as     -> Tuple as-gradBPN f = snd . backpropN f+gradBPN = E.gradBPN E.zeroFuncs E.oneFunc {-# INLINE gradBPN #-}  -- | 'backprop' for a two-argument function. -- -- Not strictly necessary, because you can always uncurry a function by--- passing in all of the argument inside a data type, or use 'T2'. However,--- this could potentially be more performant.+-- passing in all of the argument inside a data type, or just use a tuple.+-- However, this could potentially be more performant. -- -- For 3 and more arguments, consider using 'backpropN'. backprop2-    :: forall a b c. (Num a, Num b, Num c)+    :: (Backprop a, Backprop b, Backprop c)     => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)     -> a     -> b     -> (c, (a, b))-backprop2 f x y = second (\(dx ::< dy ::< Ø) -> (dx, dy))-                $ backpropN (\(x' :< y' :< Ø) -> f x' y') (x ::< y ::< Ø)+backprop2 = E.backprop2 E.zeroFunc E.zeroFunc E.oneFunc {-# INLINE backprop2 #-} --- | 'evalBP' for a two-argument function.  See 'backprop2' for notes.-evalBP2-    :: (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+-- | 'backprop2', but allows you to provide the gradient of the "final+-- result" with respect to the output of your function.  See 'backpropWith'+-- for more details.+--+-- @since 0.2.0.0+backpropWith2+    :: (Backprop a, Backprop b)+    => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)     -> a     -> b-    -> c-evalBP2 f x y = evalBPN (\(x' :< y' :< Ø) -> f x' y') (x ::< y ::< Ø)-{-# INLINE evalBP2 #-}+    -> (c -> c)                 -- ^ Gradient of final result with respect to output of function+    -> (c, (a, b))+backpropWith2 = E.backpropWith2 E.zeroFunc E.zeroFunc+{-# INLINE backpropWith2 #-}  -- | 'gradBP' for a two-argument function.  See 'backprop2' for notes. gradBP2-    :: (Num a, Num b, Num c)+    :: (Backprop a, Backprop b, Backprop c)     => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)     -> a     -> b     -> (a, b)-gradBP2 f x = snd . backprop2 f x+gradBP2 = E.gradBP2 E.zeroFunc E.zeroFunc E.oneFunc {-# INLINE gradBP2 #-}  -- | An infix version of 'viewVar', meant to evoke parallels to '^.' from@@ -288,7 +337,7 @@ -- the contents (like 'multiplying'). -- (^^.)-    :: forall a b s. (Reifies s W, Num a)+    :: forall a b s. (Reifies s W, Backprop a)     => BVar s b     -> Lens' b a     -> BVar s a@@ -296,6 +345,19 @@ infixl 8 ^^. {-# INLINE (^^.) #-} +-- | Using a 'Lens'', extract a value /inside/ a 'BVar'.  Meant to evoke+-- parallels to 'view' from lens.+--+-- See documentation for '^^.' for more information.+viewVar+    :: forall a b s. (Reifies s W, Backprop a)+    => Lens' b a+    -> BVar s b+    -> BVar s a+viewVar = E.viewVar E.addFunc E.zeroFunc+{-# INLINE viewVar #-}++ -- | An infix version of 'setVar', meant to evoke parallels to '.~' from -- lens. --@@ -320,7 +382,7 @@ -- This is the main way to set values inside 'BVar's of container types. -- (.~~)-    :: forall a b s. (Reifies s W, Num a, Num b)+    :: forall a b s. (Reifies s W, Backprop a, Backprop b)     => Lens' b a     -> BVar s a     -> BVar s b@@ -329,6 +391,20 @@ infixl 8 .~~ {-# INLINE (.~~) #-} +-- | Using a 'Lens'', set a value /inside/ a 'BVar'.  Meant to evoke+-- parallels to "set" from lens.+--+-- See documentation for '.~~' for more information.+setVar+    :: forall a b s. (Reifies s W, Backprop a, Backprop b)+    => Lens' b a+    -> BVar s a+    -> BVar s b+    -> BVar s b+setVar = E.setVar E.addFunc E.addFunc E.zeroFunc E.zeroFunc+{-# INLINE setVar #-}++ -- | An infix version of 'previewVar', meant to evoke parallels to '^?' -- from lens. --@@ -358,30 +434,28 @@ -- -- This can be used to "pattern match" on 'BVar's, by using prisms on -- constructors.------ Note that many automatically-generated prisms by the /lens/ package use--- tuples, which cannot normally be backpropagated (because they do not--- have a 'Num' instance).------ If you are writing an application or don't have to worry about orphan--- instances, you can pull in the orphan instances from--- <https://hackage.haskell.org/package/NumInstances NumInstances>.--- Alternatively, you can chain those prisms with conversions to the--- anonymous canonical strict tuple types in "Numeric.Backprop.Tuple",--- which do have 'Num' instances.------ @--- myPrism                   :: 'Prism'' c (a, b)--- myPrism . 'iso' 'tupT2' 't2Tup' :: 'Prism'' c ('T2' a b)--- @ (^^?)-    :: forall b a s. (Num a, Reifies s W)+    :: forall b a s. (Backprop a, Reifies s W)     => BVar s b     -> Traversal' b a     -> Maybe (BVar s a) v ^^? t = previewVar t v {-# INLINE (^^?) #-} +-- | Using a 'Traversal'', extract a single value /inside/ a 'BVar', if it+-- exists.  If more than one traversal target exists, returns te first.+-- Meant to evoke parallels to 'preview' from lens.  Really only intended+-- to be used wth 'Prism''s, or up-to-one target traversals.+--+-- See documentation for '^^?' for more information.+previewVar+    :: forall b a s. (Reifies s W, Backprop a)+    => Traversal' b a+    -> BVar s b+    -> Maybe (BVar s a)+previewVar = E.previewVar E.addFunc E.zeroFunc+{-# INLINE previewVar #-}+ -- | An infix version of 'toListOfVar', meant to evoke parallels to '^..' -- from lens. --@@ -404,13 +478,120 @@ -- has type @['BVar' s a]@ (A list of 'BVar's holding @a@s). -- (^^..)-    :: forall b a s. (Num a, Reifies s W)+    :: forall b a s. (Backprop a, Reifies s W)     => BVar s b     -> Traversal' b a     -> [BVar s a] v ^^.. t = toListOfVar t v {-# INLINE (^^..) #-} +-- | Using a 'Traversal'', extract all targeted values /inside/ a 'BVar'.+-- Meant to evoke parallels to 'toListOf' from lens.+--+-- See documentation for '^^..' for more information.+toListOfVar+    :: forall b a s. (Backprop a, Reifies s W)+    => Traversal' b a+    -> BVar s b+    -> [BVar s a]+toListOfVar = E.toListOfVar E.addFunc E.zeroFunc+{-# INLINE toListOfVar #-}++-- | Extract all of the 'BVar's out of a 'Traversable' container of+-- 'BVar's.+--+-- Note that this associates gradients in order of occurrence in the+-- original data structure; the second item in the gradient is assumed to+-- correspond with the second item in the input, etc.; this can cause+-- unexpected behavior in 'Foldable' instances that don't have a fixed+-- number of items.+sequenceVar+    :: forall t a s. (Backprop a, Reifies s W, Traversable t)+    => BVar s (t a)+    -> t (BVar s a)+sequenceVar = E.sequenceVar E.addFunc E.zeroFunc+{-# INLINE sequenceVar #-}++-- | Collect all of the 'BVar's in a container into a 'BVar' of that+-- container's contents.+--+-- Note that this associates gradients in order of occurrence in the+-- original data structure; the second item in the total derivative and+-- gradient is assumed to correspond with the second item in the input,+-- etc.; this can cause unexpected behavior in 'Foldable' instances that+-- don't have a fixed number of items.+collectVar+    :: forall t a s. (Backprop a, Backprop (t a), Reifies s W, Foldable t, Functor t)+    => t (BVar s a)+    -> BVar s (t a)+collectVar = E.collectVar E.addFunc E.zeroFunc E.zeroFunc+{-# INLINE collectVar #-}++-- | Lift an 'Op' with an arbitrary number of inputs to a function on the+-- appropriate number of 'BVar's.+--+-- Should preferably be used only by libraries to provide primitive 'BVar'+-- functions for their types for users.+--+-- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more+-- information, and "Numeric.Backprop.Op#prod" for a mini-tutorial on using+-- 'Prod' and 'Tuple'.+liftOp+    :: forall as b s. (Every Backprop as, Known Length as, Backprop b, Reifies s W)+    => Op as b+    -> Prod (BVar s) as+    -> BVar s b+liftOp = E.liftOp E.addFuncs E.zeroFunc+{-# INLINE liftOp #-}++-- | Lift an 'Op' with a single input to be a function on a single 'BVar'.+--+-- Should preferably be used only by libraries to provide primitive 'BVar'+-- functions for their types for users.+--+-- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more+-- information.+liftOp1+    :: forall a b s. (Backprop a, Backprop b, Reifies s W)+    => Op '[a] b+    -> BVar s a+    -> BVar s b+liftOp1 = E.liftOp1 E.addFunc E.zeroFunc+{-# INLINE liftOp1 #-}++-- | Lift an 'Op' with two inputs to be a function on a two 'BVar's.+--+-- Should preferably be used only by libraries to provide primitive 'BVar'+-- functions for their types for users.+--+-- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more+-- information.+liftOp2+    :: forall a b c s. (Backprop a, Backprop b, Backprop c, Reifies s W)+    => Op '[a,b] c+    -> BVar s a+    -> BVar s b+    -> BVar s c+liftOp2 = E.liftOp2 E.addFunc E.addFunc E.zeroFunc+{-# INLINE liftOp2 #-}++-- | Lift an 'Op' with three inputs to be a function on a three 'BVar's.+--+-- Should preferably be used only by libraries to provide primitive 'BVar'+-- functions for their types for users.+--+-- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more+-- information.+liftOp3+    :: forall a b c d s. (Backprop a, Backprop b, Backprop c, Backprop d, Reifies s W)+    => Op '[a,b,c] d+    -> BVar s a+    -> BVar s b+    -> BVar s c+    -> BVar s d+liftOp3 = E.liftOp3 E.addFunc E.addFunc E.addFunc E.zeroFunc+{-# INLINE liftOp3 #-}+ -- | Convert the value inside a 'BVar' using a given isomorphism.  Useful -- for things like constructors. --@@ -420,7 +601,7 @@ -- -- @since 0.1.4.0 isoVar-    :: (Num a, Num b, Reifies s W)+    :: (Backprop a, Backprop b, Reifies s W)     => (a -> b)     -> (b -> a)     -> BVar s a@@ -433,7 +614,7 @@ -- -- @since 0.1.4.0 isoVar2-    :: (Num a, Num b, Num c, Reifies s W)+    :: (Backprop a, Backprop b, Backprop c, Reifies s W)     => (a -> b -> c)     -> (c -> (a, b))     -> BVar s a@@ -447,7 +628,7 @@ -- -- @since 0.1.4.0 isoVar3-    :: (Num a, Num b, Num c, Num d, Reifies s W)+    :: (Backprop a, Backprop b, Backprop c, Backprop d, Reifies s W)     => (a -> b -> c -> d)     -> (d -> (a, b, c))     -> BVar s a@@ -463,7 +644,7 @@ -- -- @since 0.1.4.0 isoVarN-    :: (Every Num as, Num b, Reifies s W)+    :: (Every Backprop as, Known Length as, Backprop b, Reifies s W)     => (Tuple as -> b)     -> (b -> Tuple as)     -> Prod (BVar s) as
+ src/Numeric/Backprop/Class.hs view
@@ -0,0 +1,649 @@+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE DefaultSignatures    #-}+{-# LANGUAGE EmptyCase            #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE LambdaCase           #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE UndecidableInstances #-}++-- |+-- Module      : Numeric.Backprop.Class+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Provides the 'Backprop' typeclass, a class for values that can be used+-- for backpropagation.+--+-- This class replaces the old (version 0.1) API relying on 'Num'.+--+-- @since 0.2.0.0++module Numeric.Backprop.Class (+  -- * Backpropagatable types+    Backprop(..)+  -- * Derived methods+  , zeroNum, addNum, oneNum+  , zeroVec, addVec, oneVec+  , zeroFunctor, addIsList, addAsList, oneFunctor+  , genericZero, genericAdd, genericOne+  -- * Generics+  , GZero(..), GAdd(..), GOne(..)+  ) where++import           Data.Complex+import           Data.Foldable hiding        (toList)+import           Data.Functor.Identity+import           Data.List.NonEmpty          (NonEmpty(..))+import           Data.Proxy+import           Data.Ratio+import           Data.Type.Combinator hiding ((:.:), Comp1)+import           Data.Type.Option+import           Data.Type.Product hiding    (toList)+import           Data.Void+import           GHC.Exts+import           GHC.Generics+import           Type.Family.List+import qualified Data.IntMap                 as IM+import qualified Data.Map                    as M+import qualified Data.Sequence               as Seq+import qualified Data.Vector                 as V+import qualified Data.Vector.Generic         as VG+import qualified Data.Vector.Primitive       as VP+import qualified Data.Vector.Storable        as VS+import qualified Data.Vector.Unboxed         as VU+import qualified Type.Family.Maybe           as M++-- | Class of values that can be backpropagated in general.+--+-- For instances of 'Num', these methods can be given by 'zeroNum',+-- 'addNum', and 'oneNum'.  There are also generic options given in+-- "Numeric.Backprop.Class" for functors, 'IsList' instances, and 'Generic'+-- instances.+--+-- @+-- instance 'Backprop' 'Double' where+--     'zero' = 'zeroNum'+--     'add' = 'addNum'+--     'one' = 'oneNum'+-- @+--+-- If you leave the body of an instance declaration blank, GHC Generics+-- will be used to derive instances if the type has a single constructor+-- and each field is an instance of 'Backprop'.+--+-- To ensure that backpropagation works in a sound way, should obey the+-- laws:+--+-- [/identity/]+--+--   * @'add' x ('zero' y) = x@+--+--   * @'add' ('zero' x) y = y@+--+-- Also implies preservation of information, making @'zipWith' ('+')@ an+-- illegal implementation for lists and vectors.+--+-- This is only expected to be true up to potential "extra zeroes" in @x@+-- and @y@ in the result.+--+-- [/commutativity/]+--+--   * @'add' x y = 'add' y x@+--+-- [/associativity/]+--+--   * @'add' x ('add' y z) = 'add' ('add' x y) z@+--+-- [/idempotence/]+--+--   * @'zero' '.' 'zero' = 'zero'@+--+--   * @'one' '.' 'one' = 'one'@+--+-- Note that not all values in the backpropagation process needs all of+-- these methods: Only the "final result" needs 'one', for example.  These+-- are all grouped under one typeclass for convenience in defining+-- instances, and also to talk about sensible laws.  For fine-grained+-- control, use the "explicit" versions of library functions (for example,+-- in "Numeric.Backprop.Explicit") instead of 'Backprop' based ones.+--+-- This typeclass replaces the reliance on 'Num' of the previous API+-- (v0.1).  'Num' is strictly more powerful than 'Backprop', and is+-- a stronger constraint on types than is necessary for proper+-- backpropagating.  In particular, 'fromInteger' is a problem for many+-- types, preventing useful backpropagation for lists, variable-length+-- vectors (like "Data.Vector") and variable-size matrices from linear+-- algebra libraries like /hmatrix/ and /accelerate/.+--+-- @since 0.2.0.0+class Backprop a where+    -- | "Zero out" all components of a value.  For scalar values, this+    -- should just be @'const' 0@.  For vectors and matrices, this should+    -- set all components to zero, the additive identity.+    --+    -- Should be idempotent:+    --+    --   * @'zero' '.' 'zero' = 'zero'@+    --+    -- Should be as /lazy/ as possible.  This behavior is observed for+    -- all instances provided by this library.+    --+    -- See 'zeroNum' for a pre-built definition for instances of 'Num' and+    -- 'zeroFunctor' for a definition for instances of 'Functor'.  If left+    -- blank, will automatically be 'genericZero', a pre-built definition+    -- for instances of 'GHC.Generic' whose fields are all themselves+    -- instances of 'Backprop'.+    zero :: a -> a+    -- | Add together two values of a type.  To combine contributions of+    -- gradients, so should be information-preserving:+    --+    --   * @'add' x ('zero' y) = x@+    --+    --   * @'add' ('zero' x) y = y@+    --+    -- Should be as /strict/ as possible.  This behavior is observed for+    -- all instances provided by this library.+    --+    -- See 'addNum' for a pre-built definition for instances of 'Num' and+    -- 'addFunctor' for a definition for instances of 'Functor'.  If left+    -- blank, will automatically be 'genericAdd', a pre-built definition+    -- for instances of 'GHC.Generic' with one constructor whose fields are+    -- all themselves instances of 'Backprop'.+    add  :: a -> a -> a+    -- | "One" all components of a value.  For scalar values, this should+    -- just be @'const' 1@.  For vectors and matrices, this should set all+    -- components to one, the multiplicative identity.+    --+    -- Should be idempotent:+    --+    --   * @'one' '.' 'one' = 'one'@+    --+    -- Should be as /lazy/ as possible.  This behavior is observed for+    -- all instances provided by this library.+    --+    -- See 'oneNum' for a pre-built definition for instances of 'Num' and+    -- 'oneFunctor' for a definition for instances of 'Functor'.  If left+    -- blank, will automatically be 'genericOne', a pre-built definition+    -- for instances of 'GHC.Generic' whose fields are all themselves+    -- instances of 'Backprop'.+    one  :: a -> a++    default zero :: (Generic a, GZero (Rep a)) => a -> a+    zero = genericZero+    {-# INLINE zero #-}+    default add :: (Generic a, GAdd (Rep a)) => a -> a -> a+    add = genericAdd+    {-# INLINE add #-}+    default one :: (Generic a, GOne (Rep a)) => a -> a+    one = genericOne+    {-# INLINE one #-}++-- | 'zero' using GHC Generics; works if all fields are instances of+-- 'Backprop'.+genericZero :: (Generic a, GZero (Rep a)) => a -> a+genericZero = to . gzero . from+{-# INLINE genericZero #-}++-- | 'add' using GHC Generics; works if all fields are instances of+-- 'Backprop', but only for values with single constructors.+genericAdd :: (Generic a, GAdd (Rep a)) => a -> a -> a+genericAdd x y = to $ gadd (from x) (from y)+{-# INLINE genericAdd #-}++-- | 'one' using GHC Generics; works if all fields are instaces of+-- 'Backprop'.+genericOne :: (Generic a, GOne (Rep a)) => a -> a+genericOne = to . gone . from+{-# INLINE genericOne #-}++-- | 'zero' for instances of 'Num'.+--+-- Is lazy in its argument.+zeroNum :: Num a => a -> a+zeroNum _ = 0+{-# INLINE zeroNum #-}++-- | 'add' for instances of 'Num'.+addNum :: Num a => a -> a -> a+addNum = (+)+{-# INLINE addNum #-}++-- | 'one' for instances of 'Num'.+--+-- Is lazy in its argument.+oneNum :: Num a => a -> a+oneNum _ = 1+{-# INLINE oneNum #-}++-- | 'zero' for instances of 'VG.Vector'.+zeroVec :: (VG.Vector v a, Backprop a) => v a -> v a+zeroVec = VG.map zero+{-# INLINE zeroVec #-}++-- | 'add' for instances of 'VG.Vector'.  Automatically pads the end of the+-- shorter vector with zeroes.+addVec :: (VG.Vector v a, Backprop a) => v a -> v a -> v a+addVec x y = case compare lX lY of+    LT -> let (y1,y2) = VG.splitAt (lY - lX) y+          in  VG.zipWith add x y1 VG.++ y2+    EQ -> VG.zipWith add x y+    GT -> let (x1,x2) = VG.splitAt (lX - lY) x+          in  VG.zipWith add x1 y VG.++ x2+  where+    lX = VG.length x+    lY = VG.length y++-- | 'one' for instances of 'VG.Vector'.+oneVec :: (VG.Vector v a, Backprop a) => v a -> v a+oneVec = VG.map one+{-# INLINE oneVec #-}++-- | 'zero' for 'Functor' instances.+zeroFunctor :: (Functor f, Backprop a) => f a -> f a+zeroFunctor = fmap zero+{-# INLINE zeroFunctor #-}++-- | 'add' for instances of 'IsList'.  Automatically pads the end of the+-- "shorter" value with zeroes.+addIsList :: (IsList a, Backprop (Item a)) => a -> a -> a+addIsList = addAsList toList fromList+{-# INLINE addIsList #-}++-- | 'add' for types that are isomorphic to a list.+-- Automatically pads the end of the "shorter" value with zeroes.+addAsList+    :: Backprop b+    => (a -> [b])       -- ^ convert to list (should form isomorphism)+    -> ([b] -> a)       -- ^ convert from list (should form isomorphism)+    -> a+    -> a+    -> a+addAsList f g x y = g $ go (f x) (f y)+  where+    go = \case+      [] -> id+      o@(x':xs) -> \case+        []    -> o+        y':ys -> add x' y' : go xs ys++-- | 'one' for instances of 'Functor'.+oneFunctor :: (Functor f, Backprop a) => f a -> f a+oneFunctor = fmap one+{-# INLINE oneFunctor #-}++++++-- | Helper class for automatically deriving 'zero' using GHC Generics.+class GZero f where+    gzero :: f t -> f t++instance Backprop a => GZero (K1 i a) where+    gzero (K1 x) = K1 (zero x)+    {-# INLINE gzero #-}++instance (GZero f, GZero g) => GZero (f :*: g) where+    gzero (x :*: y) = gzero x :*: gzero y+    {-# INLINE gzero #-}++instance (GZero f, GZero g) => GZero (f :+: g) where+    gzero (L1 x) = L1 (gzero x)+    gzero (R1 x) = R1 (gzero x)+    {-# INLINE gzero #-}++instance GZero V1 where+    gzero = \case {}+    {-# INLINE gzero #-}++instance GZero U1 where+    gzero _ = U1+    {-# INLINE gzero #-}++instance GZero f => GZero (M1 i c f) where+    gzero (M1 x) = M1 (gzero x)+    {-# INLINE gzero #-}++instance GZero f => GZero (f :.: g) where+    gzero (Comp1 x) = Comp1 (gzero x)+    {-# INLINE gzero #-}+++-- | Helper class for automatically deriving 'add' using GHC Generics.+class GAdd f where+    gadd :: f t -> f t -> f t++instance Backprop a => GAdd (K1 i a) where+    gadd (K1 x) (K1 y) = K1 (add x y)+    {-# INLINE gadd #-}++instance (GAdd f, GAdd g) => GAdd (f :*: g) where+    gadd (x1 :*: y1) (x2 :*: y2) = x3 :*: y3+      where+        !x3 = gadd x1 x2+        !y3 = gadd y1 y2+    {-# INLINE gadd #-}++instance GAdd V1 where+    gadd = \case {}+    {-# INLINE gadd #-}++instance GAdd U1 where+    gadd _ _ = U1+    {-# INLINE gadd #-}++instance GAdd f => GAdd (M1 i c f) where+    gadd (M1 x) (M1 y) = M1 (gadd x y)+    {-# INLINE gadd #-}++instance GAdd f => GAdd (f :.: g) where+    gadd (Comp1 x) (Comp1 y) = Comp1 (gadd x y)+    {-# INLINE gadd #-}+++-- | Helper class for automatically deriving 'one' using GHC Generics.+class GOne f where+    gone :: f t -> f t++instance Backprop a => GOne (K1 i a) where+    gone (K1 x) = K1 (one x)+    {-# INLINE gone #-}++instance (GOne f, GOne g) => GOne (f :*: g) where+    gone (x :*: y) = gone x :*: gone y+    {-# INLINE gone #-}++instance (GOne f, GOne g) => GOne (f :+: g) where+    gone (L1 x) = L1 (gone x)+    gone (R1 x) = R1 (gone x)+    {-# INLINE gone #-}++instance GOne V1 where+    gone = \case {}+    {-# INLINE gone #-}++instance GOne U1 where+    gone _ = U1+    {-# INLINE gone #-}++instance GOne f => GOne (M1 i c f) where+    gone (M1 x) = M1 (gone x)+    {-# INLINE gone #-}++instance GOne f => GOne (f :.: g) where+    gone (Comp1 x) = Comp1 (gone x)+    {-# INLINE gone #-}++instance Backprop Int where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance Backprop Integer where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance Integral a => Backprop (Ratio a) where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance RealFloat a => Backprop (Complex a) where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance Backprop Float where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance Backprop Double where+    zero = zeroNum+    {-# INLINE zero #-}+    add  = addNum+    {-# INLINE add #-}+    one  = oneNum+    {-# INLINE one #-}++instance Backprop a => Backprop (V.Vector a) where+    zero = zeroVec+    {-# INLINE zero #-}+    add  = addVec+    {-# INLINE add #-}+    one  = oneVec+    {-# INLINE one #-}++instance (VU.Unbox a, Backprop a) => Backprop (VU.Vector a) where+    zero = zeroVec+    {-# INLINE zero #-}+    add  = addVec+    {-# INLINE add #-}+    one  = oneVec+    {-# INLINE one #-}++instance (VS.Storable a, Backprop a) => Backprop (VS.Vector a) where+    zero = zeroVec+    {-# INLINE zero #-}+    add  = addVec+    {-# INLINE add #-}+    one  = oneVec+    {-# INLINE one #-}++instance (VP.Prim a, Backprop a) => Backprop (VP.Vector a) where+    zero = zeroVec+    {-# INLINE zero #-}+    add  = addVec+    {-# INLINE add #-}+    one  = oneVec+    {-# INLINE one #-}++-- | 'add' assumes the shorter list has trailing zeroes, and the result has+-- the length of the longest input.+instance Backprop a => Backprop [a] where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add  = addIsList+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++-- | 'add' assumes the shorter list has trailing zeroes, and the result has+-- the length of the longest input.+instance Backprop a => Backprop (NonEmpty a) where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add  = addIsList+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++-- | 'add' assumes the shorter sequence has trailing zeroes, and the result+-- has the length of the longest input.+instance Backprop a => Backprop (Seq.Seq a) where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add  = addIsList+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++-- | 'Nothing' is treated the same as @'Just' 0@.  However, 'zero', 'add',+-- and 'one' preserve 'Nothing' if all inputs are also 'Nothing'.+instance Backprop a => Backprop (Maybe a) where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add x y = asum [ add <$> x <*> y+                   , x+                   , y+                   ]+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++-- | 'add' is strict, but 'zero' and 'one' are lazy in their arguments.+instance Backprop () where+    zero _ = ()+    add () () = ()+    one _ = ()++-- | 'add' is strict+instance (Backprop a, Backprop b) => Backprop (a, b) where+    zero (x, y) = (zero x, zero y)+    {-# INLINE zero #-}+    add (x1, y1) (x2, y2) = (x3, y3)+      where+        !x3 = add x1 x2+        !y3 = add y1 y2+    {-# INLINE add #-}+    one (x, y) = (one x, one y)+    {-# INLINE one #-}++-- | 'add' is strict+instance (Backprop a, Backprop b, Backprop c) => Backprop (a, b, c) where+    zero (x, y, z) = (zero x, zero y, zero z)+    {-# INLINE zero #-}+    add (x1, y1, z1) (x2, y2, z2) = (x3, y3, z3)+      where+        !x3 = add x1 x2+        !y3 = add y1 y2+        !z3 = add z1 z2+    {-# INLINE add #-}+    one (x, y, z) = (one x, one y, one z)+    {-# INLINE one #-}++-- | 'add' is strict+instance (Backprop a, Backprop b, Backprop c, Backprop d) => Backprop (a, b, c, d) where+    zero (x, y, z, w) = (zero x, zero y, zero z, zero w)+    {-# INLINE zero #-}+    add (x1, y1, z1, w1) (x2, y2, z2, w2) = (x3, y3, z3, w3)+      where+        !x3 = add x1 x2+        !y3 = add y1 y2+        !z3 = add z1 z2+        !w3 = add w1 w2+    {-# INLINE add #-}+    one (x, y, z, w) = (one x, one y, one z, one w)+    {-# INLINE one #-}++-- | 'add' is strict+instance (Backprop a, Backprop b, Backprop c, Backprop d, Backprop e) => Backprop (a, b, c, d, e) where+    zero (x, y, z, w, v) = (zero x, zero y, zero z, zero w, zero v)+    {-# INLINE zero #-}+    add (x1, y1, z1, w1, v1) (x2, y2, z2, w2, v2) = (x3, y3, z3, w3, v3)+      where+        !x3 = add x1 x2+        !y3 = add y1 y2+        !z3 = add z1 z2+        !w3 = add w1 w2+        !v3 = add v1 v2+    {-# INLINE add #-}+    one (x, y, z, w, v) = (one x, one y, one z, one w, one v)+    {-# INLINE one #-}++instance Backprop a => Backprop (Identity a) where+    zero (Identity x) = Identity (zero x)+    {-# INLINE zero #-}+    add (Identity x) (Identity y) = Identity (add x y)+    {-# INLINE add #-}+    one (Identity x) = Identity (one x)+    {-# INLINE one #-}++instance Backprop a => Backprop (I a) where+    zero (I x) = I (zero x)+    {-# INLINE zero #-}+    add (I x) (I y) = I (add x y)+    {-# INLINE add #-}+    one (I x) = I (one x)+    {-# INLINE one #-}++-- | 'add' is strict, but 'zero' and 'one' are lazy in their arguments.+instance Backprop (Proxy a) where+    zero _ = Proxy+    {-# INLINE zero #-}+    add Proxy Proxy = Proxy+    {-# INLINE add #-}+    one _ = Proxy+    {-# INLINE one #-}++instance Backprop Void where+    zero = \case {}+    {-# INLINE zero #-}+    add = \case {}+    {-# INLINE add #-}+    one = \case {}+    {-# INLINE one #-}++-- | 'zero' and 'one' replace all current values, and 'add' merges keys+-- from both maps, adding in the case of double-occurrences.+instance (Backprop a, Ord k) => Backprop (M.Map k a) where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add  = M.unionWith add+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++-- | 'zero' and 'one' replace all current values, and 'add' merges keys+-- from both maps, adding in the case of double-occurrences.+instance (Backprop a) => Backprop (IM.IntMap a) where+    zero = zeroFunctor+    {-# INLINE zero #-}+    add  = IM.unionWith add+    {-# INLINE add #-}+    one  = oneFunctor+    {-# INLINE one #-}++instance ListC (Backprop <$> (f <$> as)) => Backprop (Prod f as) where+    zero = \case+      Ø -> Ø+      x :< xs -> zero x :< zero xs+    {-# INLINE zero #-}+    add = \case+      Ø -> \case+        Ø -> Ø+      x :< xs -> \case+        y :< ys -> add x y :< add xs ys+    {-# INLINE add #-}+    one = \case+      Ø       -> Ø+      x :< xs -> one x :< one xs+    {-# INLINE one #-}++instance M.MaybeC (Backprop M.<$> (f M.<$> a)) => Backprop (Option f a) where+    zero = \case+      Nothing_ -> Nothing_+      Just_ x  -> Just_ (zero x)+    {-# INLINE zero #-}+    add = \case+      Nothing_ -> \case+        Nothing_ -> Nothing_+      Just_ x -> \case+        Just_ y -> Just_ (add x y)+    {-# INLINE add #-}+    one = \case+      Nothing_ -> Nothing_+      Just_ x  -> Just_ (one x)+    {-# INLINE one #-}+
+ src/Numeric/Backprop/Explicit.hs view
@@ -0,0 +1,321 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs            #-}+{-# LANGUAGE PatternSynonyms  #-}+{-# LANGUAGE RankNTypes       #-}+{-# LANGUAGE TypeApplications #-}++-- |+-- Module      : Numeric.Backprop.Explicit+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Provides "explicit" versions of all of the functions in+-- "Numeric.Backprop".  Instead of relying on a 'Backprop' instance, allows+-- you to manually provide 'zero', 'add', and 'one' on a per-value basis.+--+-- It is recommended you use 'Numeric.Backprop' or 'Numeric.Backprop.Num'+-- instead, unless your type has no 'Num' instance, or you else you want to+-- avoid defining orphan 'Backprop' instances for external types.  Can also+-- be useful if mixing and matching styles.+--+-- See "Numeric.Backprop" for fuller documentation on using these+-- functions.+--+-- @since 0.2.0.0++module Numeric.Backprop.Explicit (+    -- * Types+    BVar, W, Backprop(..)+    -- * Explicit 'zero', 'add', and 'one'+  , ZeroFunc(..), zfNum, zfNums, zeroFunc, zeroFuncs+  , AddFunc(..), afNum, afNums, addFunc, addFuncs+  , OneFunc(..), ofNum, ofNums, oneFunc, oneFuncs+    -- * Running+  , backprop, evalBP, gradBP, backpropWith+    -- ** Multiple inputs+  , backprop2, evalBP2, gradBP2, backpropWith2+  , backpropN, evalBPN, gradBPN, backpropWithN, Every+    -- * Manipulating 'BVar'+  , constVar, auto, coerceVar+  -- , (^^.), (.~~), (^^?), (^^..)+  , viewVar, setVar+  , sequenceVar, collectVar+  , previewVar, toListOfVar+    -- ** With Isomorphisms+  , isoVar, isoVar2, isoVar3, isoVarN+    -- ** With 'Op's+  , liftOp+  , liftOp1, liftOp2, liftOp3+    -- * 'Op'+  , Op(..)+    -- ** Creation+  , op0, opConst, idOp+  , opConst'+    -- *** Giving gradients directly+  , op1, op2, op3+    -- *** From Isomorphisms+  , opCoerce, opTup, opIso, opIsoN, opLens+    -- *** No gradients+  , noGrad1, noGrad+    -- * Utility+    -- ** Inductive tuples/heterogeneous lists+  , Prod(..), pattern (:>), only, head'+  , Tuple, pattern (::<), only_+  , I(..)+    -- ** Misc+  , Reifies+  ) where++import           Data.Bifunctor+import           Data.Reflection+import           Data.Type.Index+import           Data.Type.Length+import           Data.Type.Product+import           Numeric.Backprop.Class+import           Numeric.Backprop.Internal+import           Numeric.Backprop.Op+import           Type.Class.Higher+import           Type.Class.Known+import           Type.Class.Witness++-- | 'ZeroFunc's for every item in a type level list based on their+-- 'Num' instances+--+-- @since 0.2.0.0+zfNums :: (Every Num as, Known Length as) => Prod ZeroFunc as+zfNums = map1 (\i -> zfNum \\ every @_ @Num i) indices++-- | 'ZeroFunc's for every item in a type level list based on their+-- 'Num' instances+--+-- @since 0.2.0.0+afNums :: (Every Num as, Known Length as) => Prod AddFunc as+afNums = map1 (\i -> afNum \\ every @_ @Num i) indices++-- | 'ZeroFunc's for every item in a type level list based on their+-- 'Num' instances+--+-- @since 0.2.0.0+ofNums :: (Every Num as, Known Length as) => Prod OneFunc as+ofNums = map1 (\i -> ofNum \\ every @_ @Num i) indices++-- | The canonical 'ZeroFunc' for instances of 'Backprop'.+--+-- @since 0.2.0.0+zeroFunc :: Backprop a => ZeroFunc a+zeroFunc = ZF zero+{-# INLINE zeroFunc #-}++-- | The canonical 'AddFunc' for instances of 'Backprop'.+--+-- @since 0.2.0.0+addFunc :: Backprop a => AddFunc a+addFunc = AF add+{-# INLINE addFunc #-}++-- | The canonical 'OneFunc' for instances of 'Backprop'.+--+-- @since 0.2.0.0+oneFunc :: Backprop a => OneFunc a+oneFunc = OF one+{-# INLINE oneFunc #-}++-- | Generate an 'ZeroFunc' for every type in a type-level list, if every+-- type has an instance of 'Backprop'.+--+-- @since 0.2.0.0+zeroFuncs :: (Every Backprop as, Known Length as) => Prod ZeroFunc as+zeroFuncs = map1 (\i -> zeroFunc \\ every @_ @Backprop i) indices++-- | Generate an 'AddFunc' for every type in a type-level list, if every+-- type has an instance of 'Backprop'.+--+-- @since 0.2.0.0+addFuncs :: (Every Backprop as, Known Length as) => Prod AddFunc as+addFuncs = map1 (\i -> addFunc \\ every @_ @Backprop i) indices++-- | Generate an 'OneFunc' for every type in a type-level list, if every+-- type has an instance of 'Backprop'.+--+-- @since 0.2.0.0+oneFuncs :: (Every Backprop as, Known Length as) => Prod OneFunc as+oneFuncs = map1 (\i -> oneFunc \\ every @_ @Backprop i) indices++-- | Shorter alias for 'constVar', inspired by the /ad/ library.+--+-- @since 0.2.0.0+auto :: a -> BVar s a+auto = constVar+{-# INLINE auto #-}++-- | 'Numeric.Backprop.backpropWithN', but with explicit 'zero'.+backpropWithN+    :: Prod ZeroFunc as+    -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, Tuple as)+backpropWithN zfs f xs g = backpropN zfs (OF g) f xs+{-# INLINE backpropWithN #-}++-- | 'Numeric.Backprop.backprop', but with explicit 'zero' and 'one'.+backprop+    :: ZeroFunc a+    -> OneFunc b+    -> (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> (b, a)+backprop zfa ofb f = second (getI . head')+                   . backpropN (zfa :< Ø) ofb (f . head')+                   . only_+{-# INLINE backprop #-}++-- | 'Numeric.Backprop.backpropWith', but with explicit 'zero'.+backpropWith+    :: ZeroFunc a+    -> (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, a)+backpropWith zfa f x g = backprop zfa (OF g) f x+{-# INLINE backpropWith #-}++-- | Turn a function @'BVar' s a -> 'BVar' s b@ into the function @a -> b@+-- that it represents.+--+-- Benchmarks show that this should have virtually no overhead over+-- directly writing a @a -> b@. 'BVar' is, in this situation, a zero-cost+-- abstraction, performance-wise.+--+-- See documentation of 'Numeric.Backprop.backprop' for more information.+evalBP :: (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> b+evalBP f = evalBPN (f . head') . only_+{-# INLINE evalBP #-}++-- | 'Numeric.Backprop.gradBP', but with explicit 'zero' and 'one'.+gradBP+    :: ZeroFunc a+    -> OneFunc b+    -> (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> a+gradBP zfa ofb f = snd . backprop zfa ofb f+{-# INLINE gradBP #-}++-- | 'Numeric.Backprop.gradBP', Nbut with explicit 'zero' and 'one'.+gradBPN+    :: Prod ZeroFunc as+    -> OneFunc b+    -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> Tuple as+gradBPN zfas ofb f = snd . backpropN zfas ofb f+{-# INLINE gradBPN #-}++-- | 'Numeric.Backprop.backprop2', but with explicit 'zero' and 'one'.+backprop2+    :: ZeroFunc a+    -> ZeroFunc b+    -> OneFunc c+    -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (c, (a, b))+backprop2 zfa zfb ofc f x y = second (\(dx ::< dy ::< Ø) -> (dx, dy)) $+    backpropN (zfa :< zfb :< Ø) ofc+        (\(x' :< y' :< Ø) -> f x' y')+        (x ::< y ::< Ø)+{-# INLINE backprop2 #-}++-- | 'Numeric.Backprop.backpropWith2', but with explicit 'zero'.+backpropWith2+    :: ZeroFunc a+    -> ZeroFunc b+    -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (c -> c)                 -- ^ Gradient of final result with respect to output of function+    -> (c, (a, b))+backpropWith2 zfa zfb f x y g = backprop2 zfa zfb (OF g) f x y+{-# INLINE backpropWith2 #-}++-- | 'evalBP' for a two-argument function.  See+-- 'Numeric.Backprop.backprop2' for notes.+evalBP2+    :: (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> c+evalBP2 f x y = evalBPN (\(x' :< y' :< Ø) -> f x' y') (x ::< y ::< Ø)+{-# INLINE evalBP2 #-}++-- | 'gradBP' for a two-argument function.  See+-- 'Numeric.Backprop.backprop2' for notes.+gradBP2+    :: ZeroFunc a+    -> ZeroFunc b+    -> OneFunc c+    -> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (a, b)+gradBP2 zfa zfb ofc f x = snd . backprop2 zfa zfb ofc f x+{-# INLINE gradBP2 #-}++-- | 'Numeric.Backprop.isoVar' with explicit 'add' and 'zero'.+isoVar+    :: Reifies s W+    => AddFunc a+    -> ZeroFunc b+    -> (a -> b)+    -> (b -> a)+    -> BVar s a+    -> BVar s b+isoVar af z f g = liftOp1 af z (opIso f g)+{-# INLINE isoVar #-}++-- | 'Numeric.Backprop.isoVar2' with explicit 'add' and 'zero'.+isoVar2+    :: Reifies s W+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc c+    -> (a -> b -> c)+    -> (c -> (a, b))+    -> BVar s a+    -> BVar s b+    -> BVar s c+isoVar2 afa afb z f g = liftOp2 afa afb z (opIso2 f g)+{-# INLINE isoVar2 #-}++-- | 'Numeric.Backprop.isoVar3' with explicit 'add' and 'zero'.+isoVar3+    :: Reifies s W+    => AddFunc a+    -> AddFunc b+    -> AddFunc c+    -> ZeroFunc d+    -> (a -> b -> c -> d)+    -> (d -> (a, b, c))+    -> BVar s a+    -> BVar s b+    -> BVar s c+    -> BVar s d+isoVar3 afa afb afc z f g = liftOp3 afa afb afc z (opIso3 f g)+{-# INLINE isoVar3 #-}++-- | 'Numeric.Backprop.isoVarN' with explicit 'add' and 'zero'.+isoVarN+    :: Reifies s W+    => Prod AddFunc as+    -> ZeroFunc b+    -> (Tuple as -> b)+    -> (b -> Tuple as)+    -> Prod (BVar s) as+    -> BVar s b+isoVarN afs z f g = liftOp afs z (opIsoN f g)+{-# INLINE isoVarN #-}
src/Numeric/Backprop/Internal.hs view
@@ -10,6 +10,7 @@ {-# LANGUAGE TupleSections       #-} {-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeInType          #-}+{-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-}  -- |@@ -32,6 +33,10 @@   , liftOp, liftOp1, liftOp2, liftOp3   , viewVar, setVar, sequenceVar, collectVar, previewVar, toListOfVar   , coerceVar+  -- * Func wrappers+  , ZeroFunc(..), zfNum+  , AddFunc(..), afNum+  , OneFunc(..), ofNum   -- * Debug   , debugSTN   , debugIR@@ -53,7 +58,7 @@ import           Data.Monoid hiding        (Any(..)) import           Data.Proxy import           Data.Reflection-import           Data.Type.Index+import           Data.Type.Conjunction import           Data.Type.Product hiding  (toList) import           Data.Type.Util import           Data.Type.Vector hiding   (itraverse)@@ -64,11 +69,70 @@ import           Numeric.Backprop.Op import           System.IO.Unsafe import           Type.Class.Higher-import           Type.Class.Witness import           Unsafe.Coerce import qualified Data.Vector               as V import qualified Data.Vector.Mutable       as MV +-- | "Zero out" all components of a value.  For scalar values, this should+-- just be @'const' 0@.  For vectors and matrices, this should set all+-- components to zero, the additive identity.+--+-- Should be idempotent: Applying the function twice is the same as+-- applying it just once.+--+-- Each type should ideally only have one 'ZeroFunc'.  This coherence+-- constraint is given by the typeclass 'Backprop'.+--+-- @since 0.2.0.0+newtype ZeroFunc a = ZF { runZF :: a -> a }++-- | Add together two values of a type.  To combine contributions of+-- gradients, so should ideally be information-preserving.+--+-- See laws for 'Backprop' for the laws this should be expected to+-- preserve.  Namely, it should be commutative and associative, with an+-- identity for a valid 'ZeroFunc'.+--+-- Each type should ideally only have one 'AddFunc'.  This coherence+-- constraint is given by the typeclass 'Backprop'.+--+-- @since 0.2.0.0+newtype AddFunc  a = AF { runAF :: a -> a -> a }++-- | "One" all components of a value.  For scalar values, this should+-- just be @'const' 1@.  For vectors and matrices, this should set all+-- components to one, the multiplicative identity.+--+-- Should be idempotent: Applying the function twice is the same as+-- applying it just once.+--+-- Each type should ideally only have one 'OneFunc'.  This coherence+-- constraint is given by the typeclass 'Backprop'.+--+-- @since 0.2.0.0+newtype OneFunc  a = OF { runOF :: a -> a }++-- | If a type has a 'Num' instance, this is the canonical 'ZeroFunc'.+--+-- @since 0.2.0.0+zfNum :: Num a => ZeroFunc a+zfNum = ZF (const 0)+{-# INLINE zfNum #-}++-- | If a type has a 'Num' instance, this is the canonical 'AddFunc'.+--+-- @since 0.2.0.0+afNum :: Num a => AddFunc a+afNum = AF (+)+{-# INLINE afNum #-}++-- | If a type has a 'Num' instance, this is the canonical 'OneFunc'.+--+-- @since 0.2.0.0+ofNum :: Num a => OneFunc a+ofNum = OF (const 1)+{-# INLINE ofNum #-}+ -- | A @'BVar' s a@ is a value of type @a@ that can be "backpropagated". -- -- Functions referring to 'BVar's are tracked by the library and can be@@ -138,13 +202,12 @@  data InpRef :: Type -> Type where     IR :: { _irIx  :: !(BVar s b)-          , _irUpd :: !(Lens' b a)-          , _irAdd :: !(a -> a -> a)+          , _irAdd :: !(a -> b -> b)           }        -> InpRef a  forceInpRef :: InpRef a -> ()-forceInpRef (IR v !_ !_) = forceBVar v `seq` ()+forceInpRef (IR v !_) = forceBVar v `seq` () {-# INLINE forceInpRef #-}  -- | Debugging string for an 'InpRef'.@@ -183,14 +246,14 @@ {-# INLINE initWengert #-}  insertNode-    :: Num a-    => TapeNode a-    -> a+    :: TapeNode a+    -> a                    -- ^ val+    -> ZeroFunc a     -> W     -> IO (BVar s a)-insertNode tn !x !w = fmap ((`BV` x) . BRIx) . atomicModifyIORef' (wRef w) $ \(!n,!t) ->+insertNode tn !x zf !w = fmap ((`BV` x) . BRIx) . atomicModifyIORef' (wRef w) $ \(!n,!t) ->     let n' = n + 1-        t' = STN 0 tn:t+        t' = STN (runZF zf x) tn : t     in  forceTapeNode tn `seq` n' `seq` t' `seq` ((n', t'), n) {-# INLINE insertNode #-} @@ -203,286 +266,283 @@ {-# INLINE constVar #-}  liftOp_-    :: forall s as b. (Reifies s W, Num b, Every Num as)-    => Op as b+    :: forall s as b. Reifies s W+    => Prod AddFunc as+    -> ZeroFunc b+    -> Op as b     -> Prod (BVar s) as     -> IO (BVar s b)-liftOp_ o !vs = case traverse1 (fmap I . bvConst) vs of-                   Just xs -> return $ constVar (evalOp o xs)-                   Nothing -> insertNode tn y (reflect (Proxy @s))+liftOp_ afs z o !vs = case traverse1 (fmap I . bvConst) vs of+    Just xs -> return $ constVar (evalOp o xs)+    Nothing -> insertNode tn y z (reflect (Proxy @s))   where     (y,g) = runOpWith o (map1 (I . _bvVal) vs)-    tn = TN { _tnInputs = imap1 go vs+    tn = TN { _tnInputs = map1 go (zipP afs vs)             , _tnGrad   = g             }-    go :: forall a. Index as a -> BVar s a -> InpRef a-    go i !v = forceBVar v `seq` (IR v id (+) \\ every @_ @Num i)+    go :: forall a. (AddFunc :&: BVar s) a -> InpRef a+    go (af :&: (!v)) = forceBVar v `seq` IR v (runAF af)     {-# INLINE go #-} {-# INLINE liftOp_ #-} --- | Lift an 'Op' with an arbitrary number of inputs to a function on the--- appropriate number of 'BVar's.------ Should preferably be used only by libraries to provide primitive 'BVar'--- functions for their types for users.------ See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more--- information, and "Numeric.Backprop.Op#prod" for a mini-tutorial on using--- 'Prod' and 'Tuple'.+-- | 'Numeric.Backprop.liftOp', but with explicit 'add' and 'zero'. liftOp-    :: forall as b s. (Reifies s W, Num b, Every Num as)-    => Op as b+    :: forall as b s. Reifies s W+    => Prod AddFunc as+    -> ZeroFunc b+    -> Op as b     -> Prod (BVar s) as     -> BVar s b-liftOp o !vs = unsafePerformIO $ liftOp_ o vs+liftOp afs z o !vs = unsafePerformIO $ liftOp_ afs z o vs {-# INLINE liftOp #-}  liftOp1_-    :: forall a b s. (Reifies s W, Num a, Num b)-    => Op '[a] b+    :: forall a b s. Reifies s W+    => AddFunc a+    -> ZeroFunc b+    -> Op '[a] b     -> BVar s a     -> IO (BVar s b)-liftOp1_ o (bvConst->Just x) = return . constVar . evalOp o $ (x ::< Ø)-liftOp1_ o v = forceBVar v `seq` insertNode tn y (reflect (Proxy @s))+liftOp1_ _  _ o (bvConst->Just x) = return . constVar . evalOp o $ (x ::< Ø)+liftOp1_ af z o v = forceBVar v `seq` insertNode tn y z (reflect (Proxy @s))   where     (y,g) = runOpWith o (_bvVal v ::< Ø)-    tn = TN { _tnInputs = IR v id (+) :< Ø+    tn = TN { _tnInputs = IR v (runAF af) :< Ø             , _tnGrad   = g             } {-# INLINE liftOp1_ #-} --- | Lift an 'Op' with a single input to be a function on a single 'BVar'.------ Should preferably be used only by libraries to provide primitive 'BVar'--- functions for their types for users.------ See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more--- information.+-- | 'Numeric.Backprop.liftOp1', but with explicit 'add' and 'zero'. liftOp1-    :: forall a b s. (Reifies s W, Num a, Num b)-    => Op '[a] b+    :: forall a b s. Reifies s W+    => AddFunc a+    -> ZeroFunc b+    -> Op '[a] b     -> BVar s a     -> BVar s b-liftOp1 o !v = unsafePerformIO $ liftOp1_ o v+liftOp1 af z o !v = unsafePerformIO $ liftOp1_ af z o v {-# INLINE liftOp1 #-}  liftOp2_-    :: forall a b c s. (Reifies s W, Num a, Num b, Num c)-    => Op '[a,b] c+    :: forall a b c s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc c+    -> Op '[a,b] c     -> BVar s a     -> BVar s b     -> IO (BVar s c)-liftOp2_ o (bvConst->Just x) (bvConst->Just y) = return . constVar . evalOp o $ x ::< y ::< Ø-liftOp2_ o v u = forceBVar v-           `seq` forceBVar u-           `seq` insertNode tn y (reflect (Proxy @s))+liftOp2_ _ _ _ o (bvConst->Just x) (bvConst->Just y)+    = return . constVar . evalOp o $ x ::< y ::< Ø+liftOp2_ afa afb z o v u = forceBVar v+                     `seq` forceBVar u+                     `seq` insertNode tn y z (reflect (Proxy @s))   where     (y,g) = runOpWith o (_bvVal v ::< _bvVal u ::< Ø)-    tn = TN { _tnInputs = IR v id (+) :< IR u id (+) :< Ø+    tn = TN { _tnInputs = IR v (runAF afa) :< IR u (runAF afb) :< Ø             , _tnGrad   = g             } {-# INLINE liftOp2_ #-} --- | Lift an 'Op' with two inputs to be a function on a two 'BVar's.------ Should preferably be used only by libraries to provide primitive 'BVar'--- functions for their types for users.------ See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more--- information.+-- | 'Numeric.Backprop.liftOp2', but with explicit 'add' and 'zero'. liftOp2-    :: forall a b c s. (Reifies s W, Num a, Num b, Num c)-    => Op '[a,b] c+    :: forall a b c s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc c+    -> Op '[a,b] c     -> BVar s a     -> BVar s b     -> BVar s c-liftOp2 o !v !u = unsafePerformIO $ liftOp2_ o v u+liftOp2 afa afb z o !v !u = unsafePerformIO $ liftOp2_ afa afb z o v u {-# INLINE liftOp2 #-}  liftOp3_-    :: forall a b c d s. (Reifies s W, Num a, Num b, Num c, Num d)-    => Op '[a,b,c] d+    :: forall a b c d s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> AddFunc c+    -> ZeroFunc d+    -> Op '[a,b,c] d     -> BVar s a     -> BVar s b     -> BVar s c     -> IO (BVar s d)-liftOp3_ o (bvConst->Just x) (bvConst->Just y) (bvConst->Just z)+liftOp3_ _ _ _ _ o (bvConst->Just x) (bvConst->Just y) (bvConst->Just z)     = return . constVar . evalOp o $ x ::< y ::< z ::< Ø-liftOp3_ o v u w = forceBVar v-             `seq` forceBVar u-             `seq` forceBVar w-             `seq` insertNode tn y (reflect (Proxy @s))+liftOp3_ afa afb afc z o v u w = forceBVar v+                           `seq` forceBVar u+                           `seq` forceBVar w+                           `seq` insertNode tn y z (reflect (Proxy @s))   where     (y, g) = runOpWith o (_bvVal v ::< _bvVal u ::< _bvVal w ::< Ø)-    tn = TN { _tnInputs = IR v id (+) :< IR u id (+) :< IR w id (+) :< Ø+    tn = TN { _tnInputs = IR v (runAF afa)+                       :< IR u (runAF afb)+                       :< IR w (runAF afc)+                       :< Ø             , _tnGrad   = g             } {-# INLINE liftOp3_ #-} --- | Lift an 'Op' with three inputs to be a function on a three 'BVar's.------ Should preferably be used only by libraries to provide primitive 'BVar'--- functions for their types for users.------ See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more--- information.+-- | 'Numeric.Backprop.liftOp3', but with explicit 'add' and 'zero'. liftOp3-    :: forall a b c d s. (Reifies s W, Num a, Num b, Num c, Num d)-    => Op '[a,b,c] d+    :: forall a b c d s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> AddFunc c+    -> ZeroFunc d+    -> Op '[a,b,c] d     -> BVar s a     -> BVar s b     -> BVar s c     -> BVar s d-liftOp3 o !v !u !w = unsafePerformIO $ liftOp3_ o v u w+liftOp3 afa afb afc z o !v !u !w = unsafePerformIO $ liftOp3_ afa afb afc z o v u w {-# INLINE liftOp3 #-} +-- TODO: can we get the zero and scale func from the bvar? viewVar_-    :: forall a b s. (Reifies s W, Num a)-    => Lens' b a+    :: forall a b s. Reifies s W+    => AddFunc a+    -> ZeroFunc a+    -> Lens' b a     -> BVar s b     -> IO (BVar s a)-viewVar_ l v = forceBVar v `seq` insertNode tn y (reflect (Proxy @s))+viewVar_ af z l v = forceBVar v `seq` insertNode tn y z (reflect (Proxy @s))   where     y = _bvVal v ^. l-    tn = TN { _tnInputs = IR v l (+) :< Ø+    tn = TN { _tnInputs = IR v (over l . runAF af) :< Ø             , _tnGrad   = only_             } {-# INLINE viewVar_ #-} --- | Using a 'Lens'', extract a value /inside/ a 'BVar'.  Meant to evoke--- parallels to 'view' from lens.------ See documentation for '^^.' for more information.+-- | 'Numeric.Backprop.viewVar', but with explicit 'add' and 'zero'. viewVar-    :: forall a b s. (Reifies s W, Num a)-    => Lens' b a+    :: forall a b s. Reifies s W+    => AddFunc a+    -> ZeroFunc a+    -> Lens' b a     -> BVar s b     -> BVar s a-viewVar l !v = unsafePerformIO $ viewVar_ l v+viewVar af z l !v = unsafePerformIO $ viewVar_ af z l v {-# INLINE viewVar #-} +-- TODO: can zero and scale func be gotten from the input bvars? setVar_-    :: forall a b s. (Reifies s W, Num a, Num b)-    => Lens' b a+    :: forall a b s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc a+    -> ZeroFunc b+    -> Lens' b a     -> BVar s a     -> BVar s b     -> IO (BVar s b)-setVar_ l w v = forceBVar v-          `seq` forceBVar w-          `seq` insertNode tn y (reflect (Proxy @s))+setVar_ afa afb za zb l w v = forceBVar v+                        `seq` forceBVar w+                        `seq` insertNode tn y zb (reflect (Proxy @s))   where     y = _bvVal v & l .~ _bvVal w-    tn = TN { _tnInputs = IR w id (+) :< IR v id (+) :< Ø-            , _tnGrad   = \d -> let (dw,dv) = l (,0) d+    tn = TN { _tnInputs = IR w (runAF afa) :< IR v (runAF afb) :< Ø+            , _tnGrad   = \d -> let (dw,dv) = l (\x -> (x, runZF za x)) d                                 in  dw ::< dv ::< Ø             } {-# INLINE setVar_ #-} --- | Using a 'Lens'', set a value /inside/ a 'BVar'.  Meant to evoke--- parallels to "set" from lens.------ See documentation for '.~~' for more information.+-- | 'Numeric.Backprop.setVar', but with explicit 'add' and 'zero'. setVar-    :: forall a b s. (Reifies s W, Num a, Num b)-    => Lens' b a+    :: forall a b s. Reifies s W+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc a+    -> ZeroFunc b+    -> Lens' b a     -> BVar s a     -> BVar s b     -> BVar s b-setVar l !w !v = unsafePerformIO $ setVar_ l w v+setVar afa afb za zb l !w !v = unsafePerformIO $ setVar_ afa afb za zb l w v {-# INLINE setVar #-} --- | Extract all of the 'BVar's out of a 'Traversable' container of--- 'BVar's.------ Note that this associates gradients in order of occurrence in the--- original data structure; the second item in the gradient is assumed to--- correspond with the second item in the input, etc.; this can cause--- unexpected behavior in 'Foldable' instances that don't have a fixed--- number of items.+-- | 'Numeric.Backprop.sequenceVar', but with explicit 'add' and 'zero'. sequenceVar-    :: forall t a s. (Reifies s W, Traversable t, Num a)-    => BVar s (t a)+    :: forall t a s. (Reifies s W, Traversable t)+    => AddFunc a+    -> ZeroFunc a+    -> BVar s (t a)     -> t (BVar s a)-sequenceVar !v = unsafePerformIO $ traverseVar' id traverse v+sequenceVar af z !v = unsafePerformIO $ traverseVar' af z id traverse v {-# INLINE sequenceVar #-} +-- TODO: can scale funcs and zeros be had from bvars and Functor instance? collectVar_-    :: forall t a s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)-    => t (BVar s a)+    :: forall t a s. (Reifies s W, Foldable t, Functor t)+    => AddFunc a+    -> ZeroFunc a+    -> ZeroFunc (t a)+    -> t (BVar s a)     -> IO (BVar s (t a))-collectVar_ !vs = withV (toList vs) $ \(vVec :: Vec n (BVar s a)) -> do+collectVar_ af z z' !vs = withV (toList vs) $ \(vVec :: Vec n (BVar s a)) -> do     let tn :: TapeNode (t a)-        tn = TN { _tnInputs = vecToProd (vmap ((\v -> IR v id (+)) . getI) vVec)-                , _tnGrad   = vecToProd-                            . listToVecDef 0 (vecLen vVec)-                            . map I . toList-                }+        tn = TN+          { _tnInputs = vecToProd (vmap ((`IR` runAF af) . getI) vVec)+          , _tnGrad   = vecToProd+                      . zipVecList (\(I v) -> I . fromMaybe (runZF z (_bvVal v))) vVec+                      . toList+          }     traverse_ (evaluate . forceBVar) vs-    insertNode tn (_bvVal <$> vs) (reflect (Proxy @s))+    insertNode tn (_bvVal <$> vs) z' (reflect (Proxy @s)) {-# INLINE collectVar_ #-} --- | Collect all of the 'BVar's in a container into a 'BVar' of that--- container's contents.------ Note that this associates gradients in order of occurrence in the--- original data structure; the second item in the total derivative and--- gradient is assumed to correspond with the second item in the input,--- etc.; this can cause unexpected behavior in 'Foldable' instances that--- don't have a fixed number of items.------ Note that this requires @t a@ to have a 'Num' instance.  If you are--- using a list, I recommend using--- <https://hackage.haskell.org/package/vector-sized vector-sized> instead:--- it's a fixed-length vector type with a very appropriate 'Num' instance!+-- | 'Numeric.Backprop.collectVar', but with explicit 'add' and 'zero'. collectVar-    :: forall t a s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)-    => t (BVar s a)+    :: forall t a s. (Reifies s W, Foldable t, Functor t)+    => AddFunc a+    -> ZeroFunc a+    -> ZeroFunc (t a)+    -> t (BVar s a)     -> BVar s (t a)-collectVar !vs = unsafePerformIO $ collectVar_ vs+collectVar af z z' !vs = unsafePerformIO $ collectVar_ af z z' vs {-# INLINE collectVar #-}  traverseVar'-    :: forall b a f s. (Num a, Reifies s W, Traversable f)-    => (b -> f a)+    :: forall b a f s. (Reifies s W, Traversable f)+    => AddFunc a+    -> ZeroFunc a+    -> (b -> f a)     -> Traversal' b a     -> BVar s b     -> IO (f (BVar s a))-traverseVar' f t v = forceBVar v-               `seq` itraverse go (f (_bvVal v))+traverseVar' af z f t v = forceBVar v+                    `seq` itraverse go (f (_bvVal v))   where     go :: Int -> a -> IO (BVar s a)-    go i y = insertNode tn y (reflect (Proxy @s))+    go i y = insertNode tn y z (reflect (Proxy @s))       where-        tn = TN { _tnInputs = IR v (ixt t i) (+) :< Ø+        tn = TN { _tnInputs = IR v (over (ixt t i) . runAF af) :< Ø                 , _tnGrad   = only_                 }     {-# INLINE go #-} {-# INLINE traverseVar' #-} --- | Using a 'Traversal'', extract a single value /inside/ a 'BVar', if it--- exists.  If more than one traversal target exists, returns te first.--- Meant to evoke parallels to 'preview' from lens.  Really only intended--- to be used wth 'Prism''s, or up-to-one target traversals.------ See documentation for '^^?' for more information.+-- | 'Numeric.Backprop.previewVar', but with explicit 'add' and 'zero'. previewVar-    :: forall b a s. (Num a, Reifies s W)-    => Traversal' b a+    :: forall b a s. Reifies s W+    => AddFunc a+    -> ZeroFunc a+    -> Traversal' b a     -> BVar s b     -> Maybe (BVar s a)-previewVar t !v = unsafePerformIO $ traverseVar' (listToMaybe . toListOf t) t v+previewVar af z t !v = unsafePerformIO $ traverseVar' af z (listToMaybe . toListOf t) t v {-# INLINE previewVar #-} --- | Using a 'Traversal'', extract all targeted values /inside/ a 'BVar'.--- Meant to evoke parallels to 'toListOf' from lens.------ See documentation for '^^..' for more information.+-- | 'Numeric.Backprop.toListOfVar', but with explicit 'add' and 'zero'. toListOfVar-    :: forall b a s. (Num a, Reifies s W)-    => Traversal' b a+    :: forall b a s. Reifies s W+    => AddFunc a+    -> ZeroFunc a+    -> Traversal' b a     -> BVar s b     -> [BVar s a]-toListOfVar t !v = unsafePerformIO $ traverseVar' (toListOf t) t v+toListOfVar af z t !v = unsafePerformIO $ traverseVar' af z (toListOf t) t v {-# INLINE toListOfVar #-}  -- | Coerce a 'BVar' contents.  Useful for things like newtype wrappers.@@ -501,27 +561,27 @@ initRunner     :: (PrimMonad m, PrimState m ~ s)     => (Int, [SomeTapeNode])-    -> (Int, [Some (Wit1 Num)])+    -> (Int, [Any])     -> m (Runner s) initRunner (n, stns) (nx,xs) = do     delts <- MV.new n     for_ (zip [n-1,n-2..] stns) $ \(i, STN z (TN{..} :: TapeNode c)) ->       MV.write delts i $ unsafeCoerce z     inps <- MV.new nx-    for_ (zip [0..] xs) $ \(i, Some (Wit1 :: Wit1 Num c)) ->-      MV.write inps i $ unsafeCoerce @c 0+    for_ (zip [0..] xs) . uncurry $ \i z ->+      MV.write inps i z     return $ R delts inps {-# INLINE initRunner #-}  gradRunner-    :: forall m b s p. (PrimMonad m, PrimState m ~ s, Num b)-    => p b+    :: forall m b s. (PrimMonad m, PrimState m ~ s)+    => b                        -- ^ one     -> Runner s     -> (Int, [SomeTapeNode])     -> m ()-gradRunner _ R{..} (n,stns) = do+gradRunner o R{..} (n,stns) = do     when (n > 0) $-      MV.write _rDelta (n - 1) (unsafeCoerce @b 1)+      MV.write _rDelta (n - 1) (unsafeCoerce o)     zipWithM_ go [n-1,n-2..] stns   where     go :: Int -> SomeTapeNode -> m ()@@ -531,65 +591,43 @@       zipWithPM_ propagate _tnInputs gs     {-# INLINE go #-}     propagate :: forall x. InpRef x -> I x -> m ()-    propagate (IR v ln (+*)) (I d) = case _bvRef v of+    propagate (IR v (+*)) (I d) = case _bvRef v of       BRInp i -> flip (MV.modify _rInputs) i $-        unsafeCoerce . (ln %~ (+* d)) . unsafeCoerce+        unsafeCoerce . (d +*) . unsafeCoerce       BRIx i -> flip (MV.modify _rDelta) i $-        unsafeCoerce . (ln %~ (+* d)) . unsafeCoerce+        unsafeCoerce . (d +*) . unsafeCoerce       BRC     -> return ()     {-# INLINE propagate #-} {-# INLINE gradRunner #-} --- | 'backprop' generalized to multiple inputs of different types.  See the--- "Numeric.Backprop.Op#prod" for a mini-tutorial on heterogeneous lists.------ Not strictly necessary, because you can always uncurry a function by--- passing in all of the inputs in a data type containing all of the--- arguments or a tuple from "Numeric.Backprop.Tuple".   You could also--- pass in a giant tuple with--- <https://hackage.haskell.org/package/NumInstances NumInstances>.--- However, this can be convenient if you don't want to make a custom--- larger tuple type or pull in orphan instances.  This could potentially--- also be more performant.------ A @'Prod' ('BVar' s) '[Double, Float, Double]@, for instance, is a tuple--- of @'BVar' s 'Double'@, @'BVar' s 'Float'@, and @'BVar' s 'Double'@, and--- can be pattern matched on using ':<' (cons) and 'Ø' (nil).------ Tuples can be built and pattern matched on using '::<' (cons) and 'Ø'--- (nil), as well.------ The @'Every' 'Num' as@ in the constraint says that every value in the--- type-level list @as@ must have a 'Num' instance.  This means you can--- use, say, @'[Double, Float, Int]@, but not @'[Double, Bool, String]@.------ If you stick to /concerete/, monomorphic usage of this (with specific--- types, typed into source code, known at compile-time), then @'Every'--- 'Num' as@ should be fulfilled automatically.---+-- | 'Numeric.Backprop.backpropN', but with explicit 'zero' and 'one'. backpropN-    :: forall as b. (Every Num as, Num b)-    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    :: forall as b. ()+    => Prod ZeroFunc as+    -> OneFunc b+    -> (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)     -> Tuple as     -> (b, Tuple as)-backpropN f !xs = (y, g)+backpropN zfs ofb f !xs = (y, g)   where     !(!tp@(!_,!_),!y) = unsafePerformIO $ fillWengert f xs     g :: Tuple as     g = runST $ do-        r <- initRunner tp (getSum `first` ifoldMap1 go xs)-        gradRunner (Proxy @b) r tp+        r <- initRunner tp $ bimap getSum (`appEndo` [])+                           . fst+                           $ zipWithPM_ go zfs xs+        gradRunner (runOF ofb y) r tp         delts <- toList <$> V.freeze (_rInputs r)         return . fromMaybe (error "backpropN") $           fillProd (\_ d -> I (unsafeCoerce d)) xs delts       where-        go :: forall a. Index as a -> I a -> (Sum Int, [Some (Wit1 Num)])-        go i (I _) = (1, [Some (Wit1 :: Wit1 Num a)]) \\ every @_ @Num i+        go :: forall a. ZeroFunc a -> I a -> ((Sum Int, Endo [Any]),())+        go zf (I x) = ((1, Endo (unsafeCoerce (runZF zf x) :)), ())         {-# INLINE go #-} {-# INLINE backpropN #-}  -- | 'evalBP' generalized to multiple inputs of different types.  See--- documentation for 'backpropN' for more details.+-- documentation for 'Numeric.Backprop.backpropN' for more details. evalBPN     :: forall as b. ()     => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)@@ -623,25 +661,25 @@   instance (Num a, Reifies s W) => Num (BVar s a) where-    (+)         = liftOp2 (+.)+    (+)         = liftOp2 afNum afNum zfNum (+.)     {-# INLINE (+) #-}-    (-)         = liftOp2 (-.)+    (-)         = liftOp2 afNum afNum zfNum (-.)     {-# INLINE (-) #-}-    (*)         = liftOp2 (*.)+    (*)         = liftOp2 afNum afNum zfNum (*.)     {-# INLINE (*) #-}-    negate      = liftOp1 negateOp+    negate      = liftOp1 afNum zfNum negateOp     {-# INLINE negate #-}-    signum      = liftOp1 signumOp+    signum      = liftOp1 afNum zfNum signumOp     {-# INLINE signum #-}-    abs         = liftOp1 absOp+    abs         = liftOp1 afNum zfNum absOp     {-# INLINE abs #-}     fromInteger = constVar . fromInteger     {-# INLINE fromInteger #-}  instance (Fractional a, Reifies s W) => Fractional (BVar s a) where-    (/)          = liftOp2 (/.)+    (/)          = liftOp2 afNum afNum zfNum (/.)     {-# INLINE (/) #-}-    recip        = liftOp1 recipOp+    recip        = liftOp1 afNum zfNum recipOp     {-# INLINE recip #-}     fromRational = constVar . fromRational     {-# INLINE fromRational #-}@@ -649,39 +687,39 @@ instance (Floating a, Reifies s W) => Floating (BVar s a) where     pi      = constVar pi     {-# INLINE pi #-}-    exp     = liftOp1 expOp+    exp     = liftOp1 afNum zfNum expOp     {-# INLINE exp #-}-    log     = liftOp1 logOp+    log     = liftOp1 afNum zfNum logOp     {-# INLINE log #-}-    sqrt    = liftOp1 sqrtOp+    sqrt    = liftOp1 afNum zfNum sqrtOp     {-# INLINE sqrt #-}-    (**)    = liftOp2 (**.)+    (**)    = liftOp2 afNum afNum zfNum (**.)     {-# INLINE (**) #-}-    logBase = liftOp2 logBaseOp+    logBase = liftOp2 afNum afNum zfNum logBaseOp     {-# INLINE logBase #-}-    sin     = liftOp1 sinOp+    sin     = liftOp1 afNum zfNum sinOp     {-# INLINE sin #-}-    cos     = liftOp1 cosOp+    cos     = liftOp1 afNum zfNum cosOp     {-# INLINE cos #-}-    tan     =  liftOp1 tanOp+    tan     = liftOp1 afNum zfNum tanOp     {-# INLINE tan  #-}-    asin    = liftOp1 asinOp+    asin    = liftOp1 afNum zfNum asinOp     {-# INLINE asin #-}-    acos    = liftOp1 acosOp+    acos    = liftOp1 afNum zfNum acosOp     {-# INLINE acos #-}-    atan    = liftOp1 atanOp+    atan    = liftOp1 afNum zfNum atanOp     {-# INLINE atan #-}-    sinh    = liftOp1 sinhOp+    sinh    = liftOp1 afNum zfNum sinhOp     {-# INLINE sinh #-}-    cosh    = liftOp1 coshOp+    cosh    = liftOp1 afNum zfNum coshOp     {-# INLINE cosh #-}-    tanh    = liftOp1 tanhOp+    tanh    = liftOp1 afNum zfNum tanhOp     {-# INLINE tanh #-}-    asinh   = liftOp1 asinhOp+    asinh   = liftOp1 afNum zfNum asinhOp     {-# INLINE asinh #-}-    acosh   = liftOp1 acoshOp+    acosh   = liftOp1 afNum zfNum acoshOp     {-# INLINE acosh #-}-    atanh   = liftOp1 atanhOp+    atanh   = liftOp1 afNum zfNum atanhOp     {-# INLINE atanh #-}  -- | Compares the values inside the 'BVar'.@@ -727,4 +765,3 @@         go []     = error "asList"         go (y:ys) = (y, ys) {-# INLINE ixt #-}-
+ src/Numeric/Backprop/Num.hs view
@@ -0,0 +1,426 @@+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE GADTs             #-}+{-# LANGUAGE PatternSynonyms   #-}+{-# LANGUAGE RankNTypes        #-}++-- |+-- Module      : Numeric.Backprop.Num+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Provides the exact same API as "Numeric.Backprop", except requiring+-- 'Num' instances for all types involved instead of 'Backprop' instances.+--+-- This was the original API of the library (for version 0.1).+--+-- 'Num' is strictly more powerful than 'Backprop', and is a stronger+-- constraint on types than is necessary for proper backpropagating.  In+-- particular, 'fromInteger' is a problem for many types, preventing useful+-- backpropagation for lists, variable-length vectors (like "Data.Vector")+-- and variable-size matrices from linear algebra libraries like /hmatrix/+-- and /accelerate/.+--+-- However, this module might be useful in situations where you are working+-- with external types with 'Num' instances, and you want to avoid writing+-- orphan instances for external types.+--+-- If you have external types that are not 'Num' instances, consider+-- instead "Numeric.Backprop.External".+--+-- If you need a 'Num' instance for tuples, you can use the canonical 2-+-- and 3-tuples for the library in "Numeric.Backprop.Tuple".  If you need+-- one for larger tuples, consider making a custom product type instead+-- (making Num instances with something like+-- <https://hackage.haskell.org/package/one-liner-instances+-- one-liner-instances>).  You can also use the orphan instances in the+-- <https://hackage.haskell.org/package/NumInstances NumInstances> package+-- (in particular, "Data.NumInstances.Tuple") if you are writing an+-- application and do not have to worry about orphan instances.+--+-- See "Numeric.Backprop" for fuller documentation on using these+-- functions.+--+-- @since 0.2.0.0++module Numeric.Backprop.Num (+    -- * Types+    BVar, W+    -- * Running+  , backprop, E.evalBP, gradBP, backpropWith+    -- ** Multiple inputs+  , backprop2, E.evalBP2, gradBP2, backpropWith2+  , backpropN, E.evalBPN, gradBPN, backpropWithN, Every+    -- * Manipulating 'BVar'+  , E.constVar, E.auto, E.coerceVar+  , (^^.), (.~~), (^^?), (^^..)+  , viewVar, setVar+  , sequenceVar, collectVar+  , previewVar, toListOfVar+    -- ** With Isomorphisms+  , isoVar, isoVar2, isoVar3, isoVarN+    -- ** With 'Op's#liftops#+    -- $liftops+  , liftOp+  , liftOp1, liftOp2, liftOp3+    -- * 'Op'+  , Op(..)+    -- ** Creation+  , op0, opConst, idOp+  , opConst'+    -- *** Giving gradients directly+  , op1, op2, op3+    -- *** From Isomorphisms+  , opCoerce, opTup, opIso, opIsoN, opLens+    -- *** No gradients+  , noGrad1, noGrad+    -- * Utility+    -- ** Inductive tuples/heterogeneous lists+  , Prod(..), pattern (:>), only, head'+  , Tuple, pattern (::<), only_+  , I(..)+    -- ** Misc+  , Reifies+  ) where++import           Data.Reflection+import           Data.Type.Index+import           Data.Type.Length+import           Lens.Micro+import           Numeric.Backprop.Explicit (BVar, W)+import           Numeric.Backprop.Op+import           Type.Class.Known+import qualified Numeric.Backprop.Explicit as E++-- | 'Numeric.Backprop.backpropN', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- The @'Every' 'Num' as@ in the constraint says that every value in the+-- type-level list @as@ must have a 'Num' instance.  This means you can+-- use, say, @'[Double, Float, Int]@, but not @'[Double, Bool, String]@.+--+-- If you stick to /concerete/, monomorphic usage of this (with specific+-- types, typed into source code, known at compile-time), then @'Every'+-- 'Num' as@ should be fulfilled automatically.+--+backpropN+    :: (Every Num as, Known Length as, Num b)+    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> (b, Tuple as)+backpropN = E.backpropN E.zfNums E.ofNum+{-# INLINE backpropN #-}++-- | 'Numeric.Backprop.backpropWithN', but with 'Num' constraints instead+-- of 'Backprop' constraints.+--+-- See 'backpropN' for information on the 'Every' constraint.+backpropWithN+    :: (Every Num as, Known Length as)+    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, Tuple as)+backpropWithN = E.backpropWithN E.zfNums+{-# INLINE backpropWithN #-}++-- | 'Numeric.Backprop.backprop', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- See module documentation for "Numeric.Backprop.Num" for information on+-- using this with tuples.+backprop+    :: (Num a, Num b)+    => (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> (b, a)+backprop = E.backprop E.zfNum E.ofNum+{-# INLINE backprop #-}++-- | 'Numeric.Backprop.backpropWith', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- See module documentation for "Numeric.Backprop.Num" for information on+-- using this with tuples.+backpropWith+    :: Num a+    => (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> (b -> b)                 -- ^ Gradient of final result with respect to output of function+    -> (b, a)+backpropWith = E.backpropWith E.zfNum+{-# INLINE backpropWith #-}++-- | 'Numeric.Backprop.gradBP', but with 'Num' constraints instead of+-- 'Backprop' constraints.+gradBP+    :: (Num a, Num b)+    => (forall s. Reifies s W => BVar s a -> BVar s b)+    -> a+    -> a+gradBP = E.gradBP E.zfNum E.ofNum+{-# INLINE gradBP #-}++-- | 'Numeric.Backprop.gradBPN', but with 'Num' constraints instead of+-- 'Backprop' constraints.+gradBPN+    :: (Every Num as, Known Length as, Num b)+    => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b)+    -> Tuple as+    -> Tuple as+gradBPN = E.gradBPN E.zfNums E.ofNum+{-# INLINE gradBPN #-}++-- | 'Numeric.Backprop.backprop2', but with 'Num' constraints instead of+-- 'Backprop' constraints.+backprop2+    :: (Num a, Num b, Num c)+    => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (c, (a, b))+backprop2 = E.backprop2 E.zfNum E.zfNum E.ofNum+{-# INLINE backprop2 #-}++-- | 'Numeric.Backprop.backpropWith2', but with 'Num' constraints instead of+-- 'Backprop' constraints.+backpropWith2+    :: (Num a, Num b)+    => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (c -> c)                 -- ^ Gradient of final result with respect to output of function+    -> (c, (a, b))+backpropWith2 = E.backpropWith2 E.zfNum E.zfNum+{-# INLINE backpropWith2 #-}++-- | 'Numeric.Backprop.gradBP2', but with 'Num' constraints instead of+-- 'Backprop' constraints.+gradBP2+    :: (Num a, Num b, Num c)+    => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c)+    -> a+    -> b+    -> (a, b)+gradBP2 = E.gradBP2 E.zfNum E.zfNum E.ofNum+{-# INLINE gradBP2 #-}++-- | 'Numeric.Backprop.^^.', but with 'Num' constraints instead of+-- 'Backprop' constraints.+(^^.)+    :: forall a b s. (Reifies s W, Num a)+    => BVar s b+    -> Lens' b a+    -> BVar s a+x ^^. l = viewVar l x+infixl 8 ^^.+{-# INLINE (^^.) #-}++-- | 'Numeric.Backprop.viewVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+viewVar+    :: forall a b s. (Reifies s W, Num a)+    => Lens' b a+    -> BVar s b+    -> BVar s a+viewVar = E.viewVar E.afNum E.zfNum+{-# INLINE viewVar #-}+++-- | 'Numeric.Backprop..~~', but with 'Num' constraints instead of+-- 'Backprop' constraints.+(.~~)+    :: forall a b s. (Reifies s W, Num a, Num b)+    => Lens' b a+    -> BVar s a+    -> BVar s b+    -> BVar s b+l .~~ x = setVar l x+infixl 8 .~~+{-# INLINE (.~~) #-}++-- | 'Numeric.Backprop.setVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+setVar+    :: forall a b s. (Reifies s W, Num a, Num b)+    => Lens' b a+    -> BVar s a+    -> BVar s b+    -> BVar s b+setVar = E.setVar E.afNum E.afNum E.zfNum E.zfNum+{-# INLINE setVar #-}++-- | 'Numeric.Backprop.^^?', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- Note that many automatically-generated prisms by the /lens/ package use+-- tuples, which cannot work this this by default (because tuples do not+-- have a 'Num' instance).+--+-- If you are writing an application or don't have to worry about orphan+-- instances, you can pull in the orphan instances from+-- <https://hackage.haskell.org/package/NumInstances NumInstances>.+-- Alternatively, you can chain those prisms with conversions to the+-- anonymous canonical strict tuple types in "Numeric.Backprop.Tuple",+-- which do have 'Num' instances.+--+-- @+-- myPrism                   :: 'Prism'' c (a, b)+-- myPrism . 'iso' 'tupT2' 't2Tup' :: 'Prism'' c ('T2' a b)+-- @+(^^?)+    :: forall b a s. (Num a, Reifies s W)+    => BVar s b+    -> Traversal' b a+    -> Maybe (BVar s a)+v ^^? t = previewVar t v+{-# INLINE (^^?) #-}++-- | 'Numeric.Backprop.previewVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- See documentation for '^^?' for more information and important notes.+previewVar+    :: forall b a s. (Reifies s W, Num a)+    => Traversal' b a+    -> BVar s b+    -> Maybe (BVar s a)+previewVar = E.previewVar E.afNum E.zfNum+{-# INLINE previewVar #-}++-- | 'Numeric.Backprop.^^..', but with 'Num' constraints instead of+-- 'Backprop' constraints.+(^^..)+    :: forall b a s. (Num a, Reifies s W)+    => BVar s b+    -> Traversal' b a+    -> [BVar s a]+v ^^.. t = toListOfVar t v+{-# INLINE (^^..) #-}++-- | 'Numeric.Backprop.toListOfVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+toListOfVar+    :: forall b a s. (Num a, Reifies s W)+    => Traversal' b a+    -> BVar s b+    -> [BVar s a]+toListOfVar = E.toListOfVar E.afNum E.zfNum+{-# INLINE toListOfVar #-}++-- | 'Numeric.Backprop.sequenceVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+sequenceVar+    :: forall t a s. (Num a, Reifies s W, Traversable t)+    => BVar s (t a)+    -> t (BVar s a)+sequenceVar = E.sequenceVar E.afNum E.zfNum+{-# INLINE sequenceVar #-}++-- | 'Numeric.Backprop.collectVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+--+-- If you are using a list or vector, I recommend using+-- <https://hackage.haskell.org/package/vector-sized vector-sized> instead:+-- it's a fixed-length vector type with a very appropriate 'Num' instance!+collectVar+    :: forall t a s. (Num a, Num (t a), Reifies s W, Foldable t, Functor t)+    => t (BVar s a)+    -> BVar s (t a)+collectVar = E.collectVar E.afNum E.zfNum E.zfNum+{-# INLINE collectVar #-}++-- | 'Numeric.Backprop.liftOp', but with 'Num' constraints instead of+-- 'Backprop' constraints.+liftOp+    :: forall as b s. (Every Num as, Known Length as, Num b, Reifies s W)+    => Op as b+    -> Prod (BVar s) as+    -> BVar s b+liftOp = E.liftOp E.afNums E.zfNum+{-# INLINE liftOp #-}++-- | 'Numeric.Backprop.liftOp1', but with 'Num' constraints instead of+-- 'Backprop' constraints.+liftOp1+    :: forall a b s. (Num a, Num b, Reifies s W)+    => Op '[a] b+    -> BVar s a+    -> BVar s b+liftOp1 = E.liftOp1 E.afNum E.zfNum+{-# INLINE liftOp1 #-}++-- | 'Numeric.Backprop.liftOp2', but with 'Num' constraints instead of+-- 'Backprop' constraints.+liftOp2+    :: forall a b c s. (Num a, Num b, Num c, Reifies s W)+    => Op '[a,b] c+    -> BVar s a+    -> BVar s b+    -> BVar s c+liftOp2 = E.liftOp2 E.afNum E.afNum E.zfNum+{-# INLINE liftOp2 #-}++-- | 'Numeric.Backprop.liftOp3', but with 'Num' constraints instead of+-- 'Backprop' constraints.+liftOp3+    :: forall a b c d s. (Num a, Num b, Num c, Num d, Reifies s W)+    => Op '[a,b,c] d+    -> BVar s a+    -> BVar s b+    -> BVar s c+    -> BVar s d+liftOp3 = E.liftOp3 E.afNum E.afNum E.afNum E.zfNum+{-# INLINE liftOp3 #-}++-- | 'Numeric.Backprop.isoVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+isoVar+    :: (Num a, Num b, Reifies s W)+    => (a -> b)+    -> (b -> a)+    -> BVar s a+    -> BVar s b+isoVar f g = liftOp1 (opIso f g)+{-# INLINE isoVar #-}++-- | 'Numeric.Backprop.isoVar', but with 'Num' constraints instead of+-- 'Backprop' constraints.+isoVar2+    :: (Num a, Num b, Num c, Reifies s W)+    => (a -> b -> c)+    -> (c -> (a, b))+    -> BVar s a+    -> BVar s b+    -> BVar s c+isoVar2 f g = liftOp2 (opIso2 f g)+{-# INLINE isoVar2 #-}++-- | 'Numeric.Backprop.isoVar3', but with 'Num' constraints instead of+-- 'Backprop' constraints.+isoVar3+    :: (Num a, Num b, Num c, Num d, Reifies s W)+    => (a -> b -> c -> d)+    -> (d -> (a, b, c))+    -> BVar s a+    -> BVar s b+    -> BVar s c+    -> BVar s d+isoVar3 f g = liftOp3 (opIso3 f g)+{-# INLINE isoVar3 #-}++-- | 'Numeric.Backprop.isoVarN', but with 'Num' constraints instead of+-- 'Backprop' constraints.+isoVarN+    :: (Every Num as, Known Length as, Num b, Reifies s W)+    => (Tuple as -> b)+    -> (b -> Tuple as)+    -> Prod (BVar s) as+    -> BVar s b+isoVarN f g = liftOp (opIsoN f g)+{-# INLINE isoVarN #-}+
src/Numeric/Backprop/Op.hs view
@@ -32,6 +32,9 @@ -- of functions, 'Op' and its utility functions alone are sufficient to -- differentiate/backprop.  However, this happens rarely in practice. --+-- To use these 'Op's with the backprop library, they can be made to work+-- with 'BVar's using 'liftOp', 'liftOp1', 'liftOp2', and 'liftOp3'.+--  module Numeric.Backprop.Op (   -- * Implementation@@ -170,6 +173,9 @@ -- -- See "Numeric.Backprop.Op#prod" for a mini-tutorial on using 'Prod' and -- 'Tuple'.+--+-- To /use/ an 'Op' with the backprop library, see 'liftOp', 'liftOp1',+-- 'liftOp2', and 'liftOp3'. newtype Op as a =     -- | Construct an 'Op' by giving a function creating the     -- result, and also a continuation on how to create the gradient, given
− src/Numeric/Backprop/Tuple.hs
@@ -1,712 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes   #-}-{-# LANGUAGE CPP                   #-}-{-# LANGUAGE ConstraintKinds       #-}-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE DeriveFunctor         #-}-{-# LANGUAGE DeriveGeneric         #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE LambdaCase            #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE StandaloneDeriving    #-}-{-# LANGUAGE TupleSections         #-}-{-# LANGUAGE TypeApplications      #-}-{-# LANGUAGE TypeInType            #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE UndecidableInstances  #-}-{-# LANGUAGE ViewPatterns          #-}---- |--- Module      : Numeric.Backprop.Tuple--- Copyright   : (c) Justin Le 2018--- License     : BSD3------ Maintainer  : justin@jle.im--- Stability   : experimental--- Portability : non-portable------ Canonical strict tuples (and unit) with 'Num' instances for usage with--- /backprop/. This is here to solve the problem of orphan instances in--- libraries and potential mismatched tuple types.------ If you are writing a library that needs to export 'BVar's of tuples,--- consider using the tuples in this module so that your library can have--- easy interoperability with other libraries using /backprop/.------ Because of API decisions, 'backprop' and 'gradBP' only work with things--- with 'Num' instances.  However, this disallows default 'Prelude' tuples--- (without orphan instances from packages like--- <https://hackage.haskell.org/package/NumInstances NumInstances>).------ Until tuples have 'Num' instances in /base/, this module is intended to--- be a workaround for situations where:------ This comes up often in cases where:------     (1) A function wants to return more than one value (@'BVar' s ('T2'---     a b)@---     (2) You want to uncurry a 'BVar' function to use with 'backprop' and---     'gradBP'.---     (3) You want to use the useful 'Prism's automatically generated by---     the lens library, which use tuples for multiple-constructor fields.------ Only 2-tuples and 3-tuples are provided.  Any more and you should--- probably be using your own custom product types, with instances--- automatically generated from something like--- <https://hackage.haskell.org/package/one-liner-instances one-liner-instances>.------ Lenses into the fields are provided, but they also work with '_1', '_2',--- and '_3' from "Lens.Micro".  However, note that these are incompatible--- with '_1', '_2', and '_3' from "Control.Lens".------ You can "construct" a @'BVar' s ('T2' a b)@ with functions like--- 'isoVar'.------ @since 0.1.1.0------module Numeric.Backprop.Tuple (-  -- * Zero-tuples (unit)-    T0(..)-  -- * Two-tuples-  , T2(..)-  -- ** Conversions-  -- $t2iso-  , t2Tup, tupT2-  -- ** Consumption-  , uncurryT2, curryT2-  -- ** Lenses-  , t2_1, t2_2-  -- * Three-tuples-  , T3(..)-  -- ** Conversions-  -- $t3iso-  , t3Tup, tupT3-  -- ** Lenses-  , t3_1, t3_2, t3_3-  -- ** Consumption-  , uncurryT3, curryT3-  -- * N-Tuples-  , T(..)-  , indexT-  -- ** Conversions-  -- $tiso-  , tOnly, onlyT, tSplit, tAppend, tProd, prodT-  -- ** Lenses-  , tIx, tHead, tTail, tTake, tDrop-  -- ** Internal Utility-  , constT, mapT, zipT-  ) where--import           Control.DeepSeq-import           Control.Monad.Trans.State-import           Data.Bifunctor-import           Data.Data-import           Data.Kind-import           Data.Type.Combinator-import           Data.Type.Index-import           Data.Type.Length-import           Data.Type.Product-import           GHC.Generics               (Generic)-import           Lens.Micro-import           Lens.Micro.Internal hiding (Index)-import           System.Random-import           Type.Class.Known-import           Type.Family.List-import qualified Data.Binary                as Bi--#if !MIN_VERSION_base(4,11,0)-import           Data.Semigroup-#endif---- | Unit ('()') with 'Num', 'Fractional', and 'Floating' instances.------ Be aware that the methods in its numerical instances are all non-strict:------ @--- _ + _ = 'T0'--- 'negate' _ = 'T0'--- 'fromIntegral' _ = 'T0'--- @------ @since 0.1.4.0-data T0 = T0-  deriving (Show, Read, Eq, Ord, Generic, Data)---- | Strict 2-tuple with 'Num', 'Fractional', and 'Floating' instances.------ @since 0.1.1.0-data T2 a b   = T2 !a !b-  deriving (Show, Read, Eq, Ord, Generic, Functor, Data, Typeable)---- | Strict 3-tuple with a 'Num', 'Fractional', and 'Floating' instances.------ @since 0.1.1.0-data T3 a b c = T3 !a !b !c-  deriving (Show, Read, Eq, Ord, Generic, Functor, Data, Typeable)---- | Strict inductive N-tuple with a 'Num', 'Fractional', and 'Floating'--- instances.------ It is basically "yet another HList", like the one found in--- "Data.Type.Product" and many other locations on the haskell ecosystem.--- Because it's inductively defined, it has O(n) random indexing, but is--- efficient for zipping and mapping and other sequential consumption--- patterns.------ It is provided because of its 'Num' instance, making it useful for--- /backproup/.  Will be obsolete when 'Data.Type.Product.Product' gets--- numerical instances.------ @since 0.1.5.0-data T :: [Type] -> Type where-    TNil :: T '[]-    (:&) :: !a -> !(T as) -> T (a ': as)---- | @since 0.1.5.1-deriving instance ListC (Show <$> as) => Show (T as)--- | @since 0.1.5.1-deriving instance ListC (Eq <$> as) => Eq (T as)--- | @since 0.1.5.1-deriving instance (ListC (Eq <$> as), ListC (Ord <$> as)) => Ord (T as)--- | @since 0.1.5.1-deriving instance Typeable (T as)---- | @since 0.1.5.1-deriving instance Typeable T0--- | @since 0.1.5.1-deriving instance Typeable (T2 a b)--- | @since 0.1.5.1-deriving instance Typeable (T3 a b c)--instance NFData T0-instance (NFData a, NFData b) => NFData (T2 a b)-instance (NFData a, NFData b, NFData c) => NFData (T3 a b c)-instance ListC (NFData <$> as) => NFData (T as) where-    rnf = \case-      TNil    -> ()-      x :& xs -> rnf x `seq` rnf xs---- | @since 0.1.5.2-instance Random T0 where-    randomR  _   = (T0,)-    random       = (T0,)-    randomRs _ _ = repeat T0-    randoms  _   = repeat T0-    randomIO     = pure T0---- | @since 0.1.5.2-instance (Random a, Random b) => Random (T2 a b) where-    randomR (T2 lx ly, T2 ux uy) = runState $-        T2 <$> state (randomR (lx, ux))-           <*> state (randomR (ly, uy))-    random = runState $-        T2 <$> state random <*> state random---- | @since 0.1.5.2-instance (Random a, Random b, Random c) => Random (T3 a b c) where-    randomR (T3 lx ly lz, T3 ux uy uz) = runState $-        T3 <$> state (randomR (lx, ux))-           <*> state (randomR (ly, uy))-           <*> state (randomR (lz, uz))-    random = runState $-        T3 <$> state random <*> state random <*> state random------ TODO: optimize?---- | @since 0.1.5.1-instance Bi.Binary T0--- | @since 0.1.5.1-instance (Bi.Binary a, Bi.Binary b) => Bi.Binary (T2 a b)--- | @since 0.1.5.1-instance (Bi.Binary a, Bi.Binary b, Bi.Binary c) => Bi.Binary (T3 a b c)--instance Bifunctor T2 where-    bimap f g (T2 x y) = T2 (f x) (g y)--instance Bifunctor (T3 a) where-    bimap f g (T3 x y z) = T3 x (f y) (g z)---- | Convert to a Haskell tuple.------ Forms an isomorphism with 'tupT2'.-t2Tup :: T2 a b -> (a, b)-t2Tup (T2 x y) = (x, y)---- | Convert from Haskell tuple.------ Forms an isomorphism with 't2Tup'.-tupT2 :: (a, b) -> T2 a b-tupT2 (x, y) = T2 x y---- | Convert to a Haskell tuple.------ Forms an isomorphism with 'tupT3'.-t3Tup :: T3 a b c -> (a, b, c)-t3Tup (T3 x y z) = (x, y, z)---- | Convert from Haskell tuple.------ Forms an isomorphism with 't3Tup'.-tupT3 :: (a, b, c) -> T3 a b c-tupT3 (x, y, z) = T3 x y z---- | A singleton 'T'------ Forms an isomorphism with 'tOnly'------ @since 0.1.5.0-onlyT :: a -> T '[a]-onlyT = (:& TNil)---- | Extract a singleton 'T'------ Forms an isomorphism with 'onlyT'------ @since 0.1.5.0-tOnly :: T '[a] -> a-tOnly (x :& _) = x---- | Uncurry a function to take in a 'T2' of its arguments------ @since 0.1.2.0-uncurryT2 :: (a -> b -> c) -> T2 a b -> c-uncurryT2 f (T2 x y) = f x y---- | Curry a function taking a 'T2' of its arguments------ @since 0.1.2.0-curryT2 :: (T2 a b -> c) -> a -> b -> c-curryT2 f x y = f (T2 x y)---- | Uncurry a function to take in a 'T3' of its arguments------ @since 0.1.2.0-uncurryT3 :: (a -> b -> c -> d) -> T3 a b c -> d-uncurryT3 f (T3 x y z) = f x y z---- | Curry a function taking a 'T3' of its arguments------ @since 0.1.2.0-curryT3 :: (T3 a b c -> d) -> a -> b -> c -> d-curryT3 f x y z = f (T3 x y z)--instance Field1 (T2 a b) (T2 a' b) a a' where-    _1 = t2_1--instance Field2 (T2 a b) (T2 a b') b b' where-    _2 = t2_2--instance Field1 (T3 a b c) (T3 a' b c) a a' where-    _1 = t3_1--instance Field2 (T3 a b c) (T3 a b' c) b b' where-    _2 = t3_2--instance Field3 (T3 a b c) (T3 a b c') c c' where-    _3 = t3_3--instance Field1 (T (a ': as)) (T (a ': as)) a a where-    _1 = tIx IZ--instance Field2 (T (a ': b ': as)) (T (a ': b ': as)) b b where-    _2 = tIx (IS IZ)--instance Field3 (T (a ': b ': c ': as)) (T (a ': b ': c ': as)) c c where-    _3 = tIx (IS (IS IZ))---- | Lens into the first field of a 'T2'.  Also exported as '_1' from--- "Lens.Micro".-t2_1 :: Lens (T2 a b) (T2 a' b) a a'-t2_1 f (T2 x y) = (`T2` y) <$> f x---- | Lens into the second field of a 'T2'.  Also exported as '_2' from--- "Lens.Micro".-t2_2 :: Lens (T2 a b) (T2 a b') b b'-t2_2 f (T2 x y) = T2 x <$> f y---- | Lens into the first field of a 'T3'.  Also exported as '_1' from--- "Lens.Micro".-t3_1 :: Lens (T3 a b c) (T3 a' b c) a a'-t3_1 f (T3 x y z) = (\x' -> T3 x' y z) <$> f x---- | Lens into the second field of a 'T3'.  Also exported as '_2' from--- "Lens.Micro".-t3_2 :: Lens (T3 a b c) (T3 a b' c) b b'-t3_2 f (T3 x y z) = (\y' -> T3 x y' z) <$> f y---- | Lens into the third field of a 'T3'.  Also exported as '_3' from--- "Lens.Micro".-t3_3 :: Lens (T3 a b c) (T3 a b c') c c'-t3_3 f (T3 x y z) = T3 x y <$> f z---- | Index into a 'T'.------ /O(i)/------ @since 0.1.5.0-indexT :: Index as a -> T as -> a-indexT = flip (^.) . tIx---- | Lens into a given index of a 'T'.------ @since 0.1.5.0-tIx :: Index as a -> Lens' (T as) a-tIx IZ     f (x :& xs) = (:& xs) <$> f x-tIx (IS i) f (x :& xs) = (x :&)  <$> tIx i f xs---- | Lens into the head of a 'T'------ @since 0.1.5.0-tHead :: Lens (T (a ': as)) (T (b ': as)) a b-tHead f (x :& xs) = (:& xs) <$> f x---- | Lens into the tail of a 'T'------ @since 0.1.5.0-tTail :: Lens (T (a ': as)) (T (a ': bs)) (T as) (T bs)-tTail f (x :& xs) = (x :&) <$> f xs---- | Append two 'T's.------ Forms an isomorphism with 'tSplit'.------ @since 0.1.5.0-tAppend :: T as -> T bs -> T (as ++ bs)-tAppend TNil      ys = ys-tAppend (x :& xs) ys = x :& tAppend xs ys-infixr 5 `tAppend`---- | Split a 'T'.  For splits known at compile-time, you can use 'known' to--- derive the 'Length' automatically.------ Forms an isomorphism with 'tAppend'.------ @since 0.1.5.0-tSplit :: Length as -> T (as ++ bs) -> (T as, T bs)-tSplit LZ     xs        = (TNil, xs)-tSplit (LS l) (x :& xs) = first (x :&) . tSplit l $ xs---- | Lens into the initial portion of a 'T'.  For splits known at--- compile-time, you can use 'known' to derive the 'Length' automatically.------ @since 0.1.5.0-tTake :: forall as bs cs. Length as -> Lens (T (as ++ bs)) (T (cs ++ bs)) (T as) (T cs)-tTake l f (tSplit l->(xs,ys)) = flip (tAppend @cs @bs) ys <$> f xs---- | Lens into the ending portion of a 'T'.  For splits known at--- compile-time, you can use 'known' to derive the 'Length' automatically.------ @since 0.1.5.0-tDrop :: forall as bs cs. Length as -> Lens (T (as ++ bs)) (T (as ++ cs)) (T bs) (T cs)-tDrop l f (tSplit l->(xs,ys)) = tAppend xs <$> f ys---- | Convert a 'T' to a 'Tuple'.------ Forms an isomorphism with 'prodT'.------ @since 0.1.5.0-tProd :: T as -> Tuple as-tProd TNil      = Ø-tProd (x :& xs) = x ::< tProd xs---- | Convert a 'Tuple' to a 'T'.------ Forms an isomorphism with 'tProd'.------ @since 0.1.5.0-prodT :: Tuple as -> T as-prodT Ø           = TNil-prodT (I x :< xs) = x :& prodT xs---instance Num T0 where-    _ + _         = T0-    _ - _         = T0-    _ * _         = T0-    negate _      = T0-    abs    _      = T0-    signum _      = T0-    fromInteger _ = T0--instance Fractional T0 where-    _ / _          = T0-    recip _        = T0-    fromRational _ = T0--instance Floating T0 where-    pi          = T0-    _ ** _      = T0-    logBase _ _ = T0-    exp   _     = T0-    log   _     = T0-    sqrt  _     = T0-    sin   _     = T0-    cos   _     = T0-    asin  _     = T0-    acos  _     = T0-    atan  _     = T0-    sinh  _     = T0-    cosh  _     = T0-    asinh _     = T0-    acosh _     = T0-    atanh _     = T0--instance Semigroup T0 where-    _ <> _ = T0--instance Monoid T0 where-    mempty = T0-    mappend = (<>)--instance (Num a, Num b) => Num (T2 a b) where-    T2 x1 y1 + T2 x2 y2 = T2 (x1 + x2) (y1 + y2)-    T2 x1 y1 - T2 x2 y2 = T2 (x1 - x2) (y1 - y2)-    T2 x1 y1 * T2 x2 y2 = T2 (x1 * x2) (y1 * y2)-    negate (T2 x y)     = T2 (negate x) (negate y)-    abs    (T2 x y)     = T2 (abs    x) (abs    y)-    signum (T2 x y)     = T2 (signum x) (signum y)-    fromInteger x       = T2 (fromInteger x) (fromInteger x)--instance (Fractional a, Fractional b) => Fractional (T2 a b) where-    T2 x1 y1 / T2 x2 y2 = T2 (x1 / x2) (y1 / y2)-    recip (T2 x y)      = T2 (recip x) (recip y)-    fromRational x      = T2 (fromRational x) (fromRational x)--instance (Floating a, Floating b) => Floating (T2 a b) where-    pi                            = T2 pi pi-    T2 x1 y1 ** T2 x2 y2          = T2 (x1 ** x2) (y1 ** y2)-    logBase (T2 x1 y1) (T2 x2 y2) = T2 (logBase x1 x2) (logBase y1 y2)-    exp   (T2 x y)                = T2 (exp   x) (exp   y)-    log   (T2 x y)                = T2 (log   x) (log   y)-    sqrt  (T2 x y)                = T2 (sqrt  x) (sqrt  y)-    sin   (T2 x y)                = T2 (sin   x) (sin   y)-    cos   (T2 x y)                = T2 (cos   x) (cos   y)-    asin  (T2 x y)                = T2 (asin  x) (asin  y)-    acos  (T2 x y)                = T2 (acos  x) (acos  y)-    atan  (T2 x y)                = T2 (atan  x) (atan  y)-    sinh  (T2 x y)                = T2 (sinh  x) (sinh  y)-    cosh  (T2 x y)                = T2 (cosh  x) (cosh  y)-    asinh (T2 x y)                = T2 (asinh x) (asinh y)-    acosh (T2 x y)                = T2 (acosh x) (acosh y)-    atanh (T2 x y)                = T2 (atanh x) (atanh y)--instance (Semigroup a, Semigroup b) => Semigroup (T2 a b) where-    T2 x1 y1 <> T2 x2 y2 = T2 (x1 <> x2) (y1 <> y2)--#if MIN_VERSION_base(4,11,0)-instance (Monoid a, Monoid b) => Monoid (T2 a b) where-#else-instance (Semigroup a, Semigroup b, Monoid a, Monoid b) => Monoid (T2 a b) where-#endif-    mappend = (<>)-    mempty  = T2 mempty mempty--instance (Num a, Num b, Num c) => Num (T3 a b c) where-    T3 x1 y1 z1 + T3 x2 y2 z2 = T3 (x1 + x2) (y1 + y2) (z1 + z2)-    T3 x1 y1 z1 - T3 x2 y2 z2 = T3 (x1 - x2) (y1 - y2) (z1 + z2)-    T3 x1 y1 z1 * T3 x2 y2 z2 = T3 (x1 * x2) (y1 * y2) (z1 + z2)-    negate (T3 x y z)         = T3 (negate x) (negate y) (negate z)-    abs    (T3 x y z)         = T3 (abs    x) (abs    y) (abs    z)-    signum (T3 x y z)         = T3 (signum x) (signum y) (signum z)-    fromInteger x             = T3 (fromInteger x) (fromInteger x) (fromInteger x)--instance (Fractional a, Fractional b, Fractional c) => Fractional (T3 a b c) where-    T3 x1 y1 z1 / T3 x2 y2 z2 = T3 (x1 / x2) (y1 / y2) (z1 / z2)-    recip (T3 x y z)          = T3 (recip x) (recip y) (recip z)-    fromRational x            = T3 (fromRational x) (fromRational x) (fromRational x)--instance (Floating a, Floating b, Floating c) => Floating (T3 a b c) where-    pi                                  = T3 pi pi pi-    T3 x1 y1 z1 ** T3 x2 y2 z2          = T3 (x1 ** x2) (y1 ** y2) (z1 ** z2)-    logBase (T3 x1 y1 z1) (T3 x2 y2 z2) = T3 (logBase x1 x2) (logBase y1 y2) (logBase z1 z2)-    exp   (T3 x y z)                    = T3 (exp   x) (exp   y) (exp   z)-    log   (T3 x y z)                    = T3 (log   x) (log   y) (log   z)-    sqrt  (T3 x y z)                    = T3 (sqrt  x) (sqrt  y) (sqrt  z)-    sin   (T3 x y z)                    = T3 (sin   x) (sin   y) (sin   z)-    cos   (T3 x y z)                    = T3 (cos   x) (cos   y) (cos   z)-    asin  (T3 x y z)                    = T3 (asin  x) (asin  y) (asin  z)-    acos  (T3 x y z)                    = T3 (acos  x) (acos  y) (acos  z)-    atan  (T3 x y z)                    = T3 (atan  x) (atan  y) (atan  z)-    sinh  (T3 x y z)                    = T3 (sinh  x) (sinh  y) (sinh  z)-    cosh  (T3 x y z)                    = T3 (cosh  x) (cosh  y) (cosh  z)-    asinh (T3 x y z)                    = T3 (asinh x) (asinh y) (asinh z)-    acosh (T3 x y z)                    = T3 (acosh x) (acosh y) (acosh z)-    atanh (T3 x y z)                    = T3 (atanh x) (atanh y) (atanh z)--instance (Semigroup a, Semigroup b, Semigroup c) => Semigroup (T3 a b c) where-    T3 x1 y1 z1 <> T3 x2 y2 z2 = T3 (x1 <> x2) (y1 <> y2) (z1 <> z2)--#if MIN_VERSION_base(4,11,0)-instance (Monoid a, Monoid b, Monoid c) => Monoid (T3 a b c) where-#else-instance (Semigroup a, Semigroup b, Semigroup c, Monoid a, Monoid b, Monoid c) => Monoid (T3 a b c) where-#endif-    mappend = (<>)-    mempty  = T3 mempty mempty mempty---- | Initialize a 'T' with a Rank-N value.  Mostly used internally, but--- provided in case useful.------ Must be used with /TypeApplications/ to provide the Rank-N constraint.------ @since 0.1.5.0-constT-    :: forall c as. ListC (c <$> as)-    => (forall a. c a => a)-    -> Length as-    -> T as-constT x = go-  where-    go :: forall bs. ListC (c <$> bs) => Length bs -> T bs-    go LZ     = TNil-    go (LS l) = x :& go l---- | Map over a 'T' with a Rank-N function.  Mostly used internally, but--- provided in case useful.------ Must be used with /TypeApplications/ to provide the Rank-N constraint.------ @since 0.1.5.0-mapT-    :: forall c as. ListC (c <$> as)-    => (forall a. c a => a -> a)-    -> T as-    -> T as-mapT f = go-  where-    go :: forall bs. ListC (c <$> bs) => T bs -> T bs-    go TNil      = TNil-    go (x :& xs) = f x :& go xs---- | Map over a 'T' with a Rank-N function.  Mostly used internally, but--- provided in case useful.------ Must be used with /TypeApplications/ to provide the Rank-N constraint.------ @since 0.1.5.0-zipT-    :: forall c as. ListC (c <$> as)-    => (forall a. c a => a -> a -> a)-    -> T as-    -> T as-    -> T as-zipT f = go-  where-    go :: forall bs. ListC (c <$> bs) => T bs -> T bs -> T bs-    go TNil      TNil      = TNil-    go (x :& xs) (y :& ys) = f x y :& go xs ys--instance (Known Length as, ListC (Num <$> as)) => Num (T as) where-    (+)           = zipT @Num (+)-    (-)           = zipT @Num (-)-    (*)           = zipT @Num (*)-    negate        = mapT @Num negate-    abs           = mapT @Num abs-    signum        = mapT @Num signum-    fromInteger x = constT @Num (fromInteger x) known--instance (Known Length as, ListC (Num <$> as), ListC (Fractional <$> as)) => Fractional (T as) where-    (/)            = zipT @Fractional (/)-    recip          = mapT @Fractional recip-    fromRational x = constT @Fractional (fromRational x) known--instance (Known Length as, ListC (Num <$> as), ListC (Fractional <$> as), ListC (Floating <$> as))-        => Floating (T as) where-    pi      = constT @Floating pi known-    (**)    = zipT @Floating (**)-    logBase = zipT @Floating logBase-    exp     = mapT @Floating exp-    log     = mapT @Floating log-    sqrt    = mapT @Floating sqrt-    sin     = mapT @Floating sin-    cos     = mapT @Floating cos-    asin    = mapT @Floating asin-    acos    = mapT @Floating acos-    atan    = mapT @Floating atan-    sinh    = mapT @Floating sinh-    cosh    = mapT @Floating cosh-    asinh   = mapT @Floating asinh-    acosh   = mapT @Floating acosh-    atanh   = mapT @Floating atanh--instance ListC (Semigroup <$> as) => Semigroup (T as) where-    (<>) = zipT @Semigroup (<>)--instance (Known Length as, ListC (Semigroup <$> as), ListC (Monoid <$> as)) => Monoid (T as) where-    mempty  = constT @Monoid mempty known-    mappend = (<>)---- | @since 0.1.5.1-instance (Known Length as, ListC (Bi.Binary <$> as)) => Bi.Binary (T as) where-    put = \case-      TNil -> pure ()-      x :& xs -> do-        Bi.put x-        Bi.put xs-    get = getT known--getT :: ListC (Bi.Binary <$> as) => Length as -> Bi.Get (T as)-getT = \case-    LZ   -> pure TNil-    LS l -> do-      x  <- Bi.get-      xs <- getT l-      pure (x :& xs)---- | @since 0.1.5.2-instance (Known Length as, ListC (Random <$> as)) => Random (T as) where-    randomR (l, u) = runState (randomRT l u)-    random         = runState (randomT known)--randomRT-    :: (ListC (Random <$> as), RandomGen g)-    => T as-    -> T as-    -> State g (T as)-randomRT = \case-    TNil -> \case-      TNil -> pure TNil-    lx :& lxs -> \case-      ux :& uxs -> (:&) <$> state (randomR (lx, ux)) <*> randomRT lxs uxs--randomT-    :: (ListC (Random <$> as), RandomGen g)-    => Length as-    -> State g (T as)-randomT = \case-    LZ   -> pure TNil-    LS l -> (:&) <$> state random <*> randomT l---- $t2iso------ If using /lens/, the two conversion functions can be chained with prisms--- and traversals and other optics using:------ @--- 'iso' 'tupT2' 't2Tup' :: 'Iso'' (a, b) ('T2' a b)--- @---- $t3iso------ If using /lens/, the two conversion functions can be chained with prisms--- and traversals and other optics using:------ @--- 'iso' 'tupT3' 't2Tup' :: 'Iso'' (a, b, c) ('T3' a b c)--- @---- $tiso------ If using /lens/, the two conversion functions can be chained with prisms--- and traversals and other optics using:------ @--- 'iso' 'onlyT' 'tOnly' :: 'Iso'' a (T '[a])--- @
src/Prelude/Backprop.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}  -- |@@ -13,15 +14,13 @@ -- Some lifted versions of common functions found in 'Prelude' (or /base/ -- in general). ----- Intended to work with 'Functor' / 'Foldable' / 'Traversable' instances--- with "fixed" number of items, i.e.--- <https://hackage.haskell.org/package/vector-sized vector-sized> vectors.--- There might be unintended consequences when using it with instances--- where the number of items is not fixed.--- -- This module is intended to be a catch-all one, so feel free to suggest -- other functions or submit a PR if you think one would make sense. --+-- See "Prelude.Backprop.Num" for a version with 'Num' constraints instead+-- of 'Backprop' constraints, and "Prelude.Backprop.Explicit" for a version+-- allowing you to provide 'zero', 'add', and 'one' explicitly.+-- -- @since 0.1.3.0 -- @@ -47,10 +46,11 @@ import           Prelude             (Num(..), Fractional(..), Eq(..), Ord(..), Functor, Foldable, Traversable, Applicative, (.), ($)) import qualified Control.Applicative as P import qualified Data.Coerce         as C+import qualified Data.Foldable       as P import qualified Prelude             as P  -- | Lifted 'P.sum'-sum :: forall t a s. (Foldable t, Functor t, Num (t a), Num a, Reifies s W)+sum :: forall t a s. (Foldable t, Functor t, Backprop (t a), Backprop a, Num a, Reifies s W)     => BVar s (t a)     -> BVar s a sum = liftOp1 . op1 $ \xs ->@@ -59,22 +59,21 @@     ) {-# INLINE sum #-} --- | Lifted 'P.pure'.  Really intended only for 'Applicative' instances--- with fixed number of items; untintended consequences might arise when--- using it with containers with variable number of items.+-- | Lifted 'P.pure'. pure-    :: forall t a s. (Foldable t, Applicative t, Num (t a), Num a, Reifies s W)+    :: forall t a s. (Foldable t, Applicative t, Backprop (t a), Backprop a, Reifies s W)     => BVar s a     -> BVar s (t a) pure = liftOp1 . op1 $ \x ->     ( P.pure x-    , P.sum+    , P.foldl' add (zero x)+    -- , P.foldl' add zero     ) {-# INLINE pure #-}  -- | Lifted 'P.product' product-    :: forall t a s. (Foldable t, Functor t, Num (t a), Fractional a, Reifies s W)+    :: forall t a s. (Foldable t, Functor t, Backprop (t a), Backprop a, Fractional a, Reifies s W)     => BVar s (t a)     -> BVar s a product = liftOp1 . op1 $ \xs ->@@ -86,49 +85,45 @@  -- | Lifted 'P.length'. length-    :: forall t a b s. (Foldable t, Num (t a), Num b, Reifies s W)+    :: forall t a b s. (Foldable t, Backprop (t a), Backprop b, Num b, Reifies s W)     => BVar s (t a)     -> BVar s b length = liftOp1 . op1 $ \xs ->     ( P.fromIntegral (P.length xs)-    , P.const 0+    , P.const (zero xs)     ) {-# INLINE length #-}  -- | Lifted 'P.minimum'.  Undefined for situations where 'P.minimum' would -- be undefined. minimum-    :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)+    :: forall t a s. (Foldable t, Functor t, Backprop a, Ord a, Backprop (t a), Reifies s W)     => BVar s (t a)     -> BVar s a minimum = liftOp1 . op1 $ \xs ->     let m = P.minimum xs     in  ( m-        , \d -> (\x -> if x == m then d else 0) P.<$> xs+        , \d -> (\x -> if x == m then d else zero x) P.<$> xs         ) {-# INLINE minimum #-}  -- | Lifted 'P.maximum'.  Undefined for situations where 'P.maximum' would -- be undefined. maximum-    :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)+    :: forall t a s. (Foldable t, Functor t, Backprop a, Ord a, Backprop (t a), Reifies s W)     => BVar s (t a)     -> BVar s a maximum = liftOp1 . op1 $ \xs ->     let m = P.maximum xs     in  ( m-        , \d -> (\x -> if x == m then d else 0) P.<$> xs+        , \d -> (\x -> if x == m then d else zero x) P.<$> xs         ) {-# INLINE maximum #-}  -- | Lifted 'P.fmap'.  Lifts backpropagatable functions to be -- backpropagatable functions on 'Traversable' 'Functor's.------ Really intended only for 'Functor' instances with fixed number of items;--- untintended consequences might arise when using it with containers with--- variable number of items. fmap-    :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W)+    :: forall f a b s. (Traversable f, Backprop a, Backprop b, Backprop (f b), Reifies s W)     => (BVar s a -> BVar s b)     -> BVar s (f a)     -> BVar s (f b)@@ -137,7 +132,7 @@  -- | Alias for 'fmap'. (<$>)-    :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W)+    :: forall f a b s. (Traversable f, Backprop a, Backprop b, Backprop (f b), Reifies s W)     => (BVar s a -> BVar s b)     -> BVar s (f a)     -> BVar s (f b)@@ -146,12 +141,8 @@  -- | Lifted 'P.traverse'.  Lifts backpropagatable functions to be -- backpropagatable functions on 'Traversable' 'Functor's.------ Really intended only for 'Traversable' and 'Applicative' instances with--- fixed number of items; untintended consequences might arise when using--- it with containers with variable number of items. traverse-    :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Num a, Num b, Num (f (t b)), Num (t b), Reifies s W)+    :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Backprop a, Backprop b, Backprop (f (t b)), Backprop (t b), Reifies s W)     => (BVar s a -> f (BVar s b))     -> BVar s (t a)     -> BVar s (f (t b))@@ -163,15 +154,11 @@  -- | Lifted 'P.liftA2'.  Lifts backpropagatable functions to be -- backpropagatable functions on 'Traversable' 'Applicative's.------ Really intended only for 'Traversable' and 'Applicative' instances with--- fixed number of items; untintended consequences might arise when using--- it with containers with variable number of items. liftA2     :: forall f a b c s.        ( Traversable f        , Applicative f-       , Num a, Num b, Num c, Num (f c)+       , Backprop a, Backprop b, Backprop c, Backprop (f c)        , Reifies s W        )     => (BVar s a -> BVar s b -> BVar s c)@@ -184,15 +171,11 @@  -- | Lifted 'P.liftA3'.  Lifts backpropagatable functions to be -- backpropagatable functions on 'Traversable' 'Applicative's.------ Really intended only for 'Traversable' and 'Applicative' instances with--- fixed number of items; untintended consequences might arise when using--- it with containers with variable number of items. liftA3     :: forall f a b c d s.        ( Traversable f        , Applicative f-       , Num a, Num b, Num c, Num d, Num (f d)+       , Backprop a, Backprop b, Backprop c, Backprop d, Backprop (f d)        , Reifies s W        )     => (BVar s a -> BVar s b -> BVar s c -> BVar s d)@@ -207,8 +190,8 @@  -- | Coerce items inside a 'BVar'. coerce-    :: forall a b s. (C.Coercible a b, Num a, Num b, Reifies s W)+    :: forall a b s. C.Coercible a b     => BVar s a     -> BVar s b-coerce = liftOp1 $ opIso C.coerce C.coerce+coerce = coerceVar {-# INLINE coerce #-}
+ src/Prelude/Backprop/Explicit.hs view
@@ -0,0 +1,225 @@+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module      : Prelude.Backprop.Explicit+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Provides "explicit" versions of all of the functions in+-- "Prelude.Backprop".  Instead of relying on a 'Backprop' instance, allows+-- you to manually provide 'zero', 'add', and 'one' on a per-value basis.+--+-- @since 0.2.0.0++module Prelude.Backprop.Explicit (+  -- * Foldable and Traversable+    sum+  , product+  , length+  , minimum+  , maximum+  , traverse+  -- * Functor and Applicative+  , fmap+  , pure+  , liftA2+  , liftA3+  -- * Misc+  , coerce+  ) where++import           Numeric.Backprop.Explicit+import           Prelude             (Num(..), Fractional(..), Eq(..), Ord(..), Functor, Foldable, Traversable, Applicative, (.), ($))+import qualified Control.Applicative as P+import qualified Data.Coerce         as C+import qualified Data.Foldable       as P+import qualified Prelude             as P++-- | Lifted 'P.sum'+sum :: forall t a s. (Foldable t, Functor t, Num a, Reifies s W)+    => AddFunc (t a)+    -> ZeroFunc a+    -> BVar s (t a)+    -> BVar s a+sum af zf = liftOp1 af zf . op1 $ \xs ->+    ( P.sum xs+    , (P.<$ xs)+    )+{-# INLINE sum #-}++-- | Lifted 'P.pure'.+pure+    :: forall t a s. (Foldable t, Applicative t, Reifies s W)+    => AddFunc a+    -> ZeroFunc a+    -> ZeroFunc (t a)+    -> BVar s a+    -> BVar s (t a)+pure af zfa zf = liftOp1 af zf . op1 $ \x ->+    ( P.pure x+    , P.foldl' (runAF af) (runZF zfa x)+    )+{-# INLINE pure #-}++-- | Lifted 'P.product'+product+    :: forall t a s. (Foldable t, Functor t, Fractional a, Reifies s W)+    => AddFunc (t a)+    -> ZeroFunc a+    -> BVar s (t a)+    -> BVar s a+product af zf = liftOp1 af zf . op1 $ \xs ->+    let p = P.product xs+    in ( p+       , \d -> (\x -> p * d / x) P.<$> xs+       )+{-# INLINE product #-}++-- | Lifted 'P.length'.+length+    :: forall t a b s. (Foldable t, Num b, Reifies s W)+    => AddFunc (t a)+    -> ZeroFunc (t a)+    -> ZeroFunc b+    -> BVar s (t a)+    -> BVar s b+length af zfa zf = liftOp1 af zf . op1 $ \xs ->+    ( P.fromIntegral (P.length xs)+    , P.const (runZF zfa xs)+    )+{-# INLINE length #-}++-- | Lifted 'P.minimum'.  Undefined for situations where 'P.minimum' would+-- be undefined.+minimum+    :: forall t a s. (Foldable t, Functor t, Ord a, Reifies s W)+    => AddFunc (t a)+    -> ZeroFunc a+    -> BVar s (t a)+    -> BVar s a+minimum af zf = liftOp1 af zf . op1 $ \xs ->+    let m = P.minimum xs+    in  ( m+        , \d -> (\x -> if x == m then d else runZF zf x) P.<$> xs+        )+{-# INLINE minimum #-}++-- | Lifted 'P.maximum'.  Undefined for situations where 'P.maximum' would+-- be undefined.+maximum+    :: forall t a s. (Foldable t, Functor t, Ord a, Reifies s W)+    => AddFunc (t a)+    -> ZeroFunc a+    -> BVar s (t a)+    -> BVar s a+maximum af zf = liftOp1 af zf . op1 $ \xs ->+    let m = P.maximum xs+    in  ( m+        , \d -> (\x -> if x == m then d else runZF zf x) P.<$> xs+        )+{-# INLINE maximum #-}++-- | Lifted 'P.fmap'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Functor's.+fmap+    :: forall f a b s. (Traversable f, Reifies s W)+    => AddFunc a+    -> AddFunc b+    -> ZeroFunc a+    -> ZeroFunc b+    -> ZeroFunc (f b)+    -> (BVar s a -> BVar s b)+    -> BVar s (f a)+    -> BVar s (f b)+fmap afa afb zfa zfb zfbs f = collectVar afb zfb zfbs . P.fmap f . sequenceVar afa zfa+{-# INLINE fmap #-}++-- | Lifted 'P.traverse'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Functor's.+traverse+    :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Reifies s W)+    => AddFunc a+    -> AddFunc b+    -> AddFunc (t b)+    -> ZeroFunc a+    -> ZeroFunc b+    -> ZeroFunc (t b)+    -> ZeroFunc (f (t b))+    -> (BVar s a -> f (BVar s b))+    -> BVar s (t a)+    -> BVar s (f (t b))+traverse afa afb aftb zfa zfb zftb zfftb f+        = collectVar aftb zftb zfftb+        . P.fmap (collectVar afb zfb zftb)+        . P.traverse f+        . sequenceVar afa zfa+{-# INLINE traverse #-}++-- | Lifted 'P.liftA2'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Applicative's.+liftA2+    :: forall f a b c s.+       ( Traversable f+       , Applicative f+       , Reifies s W+       )+    => AddFunc a+    -> AddFunc b+    -> AddFunc c+    -> ZeroFunc a+    -> ZeroFunc b+    -> ZeroFunc c+    -> ZeroFunc (f c)+    -> (BVar s a -> BVar s b -> BVar s c)+    -> BVar s (f a)+    -> BVar s (f b)+    -> BVar s (f c)+liftA2 afa afb afc zfa zfb zfc zffc f x y+    = collectVar afc zfc zffc+    $ f P.<$> sequenceVar afa zfa x+        P.<*> sequenceVar afb zfb y+{-# INLINE liftA2 #-}++-- | Lifted 'P.liftA3'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Applicative's.+liftA3+    :: forall f a b c d s.+       ( Traversable f+       , Applicative f+       , Reifies s W+       )+    => AddFunc a+    -> AddFunc b+    -> AddFunc c+    -> AddFunc d+    -> ZeroFunc a+    -> ZeroFunc b+    -> ZeroFunc c+    -> ZeroFunc d+    -> ZeroFunc (f d)+    -> (BVar s a -> BVar s b -> BVar s c -> BVar s d)+    -> BVar s (f a)+    -> BVar s (f b)+    -> BVar s (f c)+    -> BVar s (f d)+liftA3 afa afb afc afd zfa zfb zfc zfd zffd f x y z+    = collectVar afd zfd zffd+    $ f P.<$> sequenceVar afa zfa x+        P.<*> sequenceVar afb zfb y+        P.<*> sequenceVar afc zfc z+{-# INLINE liftA3 #-}++-- | Coerce items inside a 'BVar'.+coerce+    :: forall a b s. C.Coercible a b+    => BVar s a+    -> BVar s b+coerce = coerceVar+{-# INLINE coerce #-}++
+ src/Prelude/Backprop/Num.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module      : Prelude.Backprop.Num+-- Copyright   : (c) Justin Le 2018+-- License     : BSD3+--+-- Maintainer  : justin@jle.im+-- Stability   : experimental+-- Portability : non-portable+--+-- Provides the exact same API as "Prelude.Backprop", except requiring+-- 'Num' instances for all types involved instead of 'Backprop' instances.+--+-- @since 0.2.0.0++module Prelude.Backprop.Num (+  -- * Foldable and Traversable+    sum+  , product+  , length+  , minimum+  , maximum+  , traverse+  -- * Functor and Applicative+  , fmap+  , (<$>)+  , pure+  , liftA2+  , liftA3+  -- * Misc+  , coerce+  ) where++import           Numeric.Backprop.Num+import           Prelude              (Num(..), Fractional(..), Eq(..), Ord(..), Functor, Foldable, Traversable, Applicative, (.), ($))+import qualified Control.Applicative  as P+import qualified Data.Coerce          as C+import qualified Data.Foldable        as P+import qualified Prelude              as P++-- | Lifted 'P.sum'+sum :: forall t a s. (Foldable t, Functor t, Num (t a), Num a, Reifies s W)+    => BVar s (t a)+    -> BVar s a+sum = liftOp1 . op1 $ \xs ->+    ( P.sum xs+    , (P.<$ xs)+    )+{-# INLINE sum #-}++-- | Lifted 'P.pure'.+pure+    :: forall t a s. (Foldable t, Applicative t, Num (t a), Num a, Reifies s W)+    => BVar s a+    -> BVar s (t a)+pure = liftOp1 . op1 $ \x ->+    ( P.pure x+    , P.sum+    )+{-# INLINE pure #-}++-- | Lifted 'P.product'+product+    :: forall t a s. (Foldable t, Functor t, Num (t a), Fractional a, Reifies s W)+    => BVar s (t a)+    -> BVar s a+product = liftOp1 . op1 $ \xs ->+    let p = P.product xs+    in ( p+       , \d -> (\x -> p * d / x) P.<$> xs+       )+{-# INLINE product #-}++-- | Lifted 'P.length'.+length+    :: forall t a b s. (Foldable t, Num (t a), Num b, Reifies s W)+    => BVar s (t a)+    -> BVar s b+length = liftOp1 . op1 $ \xs ->+    ( P.fromIntegral (P.length xs)+    , P.const 0+    )+{-# INLINE length #-}++-- | Lifted 'P.minimum'.  Undefined for situations where 'P.minimum' would+-- be undefined.+minimum+    :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)+    => BVar s (t a)+    -> BVar s a+minimum = liftOp1 . op1 $ \xs ->+    let m = P.minimum xs+    in  ( m+        , \d -> (\x -> if x == m then d else 0) P.<$> xs+        )+{-# INLINE minimum #-}++-- | Lifted 'P.maximum'.  Undefined for situations where 'P.maximum' would+-- be undefined.+maximum+    :: forall t a s. (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)+    => BVar s (t a)+    -> BVar s a+maximum = liftOp1 . op1 $ \xs ->+    let m = P.maximum xs+    in  ( m+        , \d -> (\x -> if x == m then d else 0) P.<$> xs+        )+{-# INLINE maximum #-}++-- | Lifted 'P.fmap'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Functor's.+fmap+    :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W)+    => (BVar s a -> BVar s b)+    -> BVar s (f a)+    -> BVar s (f b)+fmap f = collectVar . P.fmap f . sequenceVar+{-# INLINE fmap #-}++-- | Alias for 'fmap'.+(<$>)+    :: forall f a b s. (Traversable f, Num a, Num b, Num (f b), Reifies s W)+    => (BVar s a -> BVar s b)+    -> BVar s (f a)+    -> BVar s (f b)+(<$>) = fmap+{-# INLINE (<$>) #-}++-- | Lifted 'P.traverse'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Functor's.+traverse+    :: forall t f a b s. (Traversable t, Applicative f, Foldable f, Num a, Num b, Num (f (t b)), Num (t b), Reifies s W)+    => (BVar s a -> f (BVar s b))+    -> BVar s (t a)+    -> BVar s (f (t b))+traverse f = collectVar+           . P.fmap collectVar+           . P.traverse f+           . sequenceVar+{-# INLINE traverse #-}++-- | Lifted 'P.liftA2'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Applicative's.+liftA2+    :: forall f a b c s.+       ( Traversable f+       , Applicative f+       , Num a, Num b, Num c, Num (f c)+       , Reifies s W+       )+    => (BVar s a -> BVar s b -> BVar s c)+    -> BVar s (f a)+    -> BVar s (f b)+    -> BVar s (f c)+liftA2 f x y = collectVar $ f P.<$> sequenceVar x+                              P.<*> sequenceVar y+{-# INLINE liftA2 #-}++-- | Lifted 'P.liftA3'.  Lifts backpropagatable functions to be+-- backpropagatable functions on 'Traversable' 'Applicative's.+liftA3+    :: forall f a b c d s.+       ( Traversable f+       , Applicative f+       , Num a, Num b, Num c, Num d, Num (f d)+       , Reifies s W+       )+    => (BVar s a -> BVar s b -> BVar s c -> BVar s d)+    -> BVar s (f a)+    -> BVar s (f b)+    -> BVar s (f c)+    -> BVar s (f d)+liftA3 f x y z = collectVar $ f P.<$> sequenceVar x+                                P.<*> sequenceVar y+                                P.<*> sequenceVar z+{-# INLINE liftA3 #-}++-- | Coerce items inside a 'BVar'.+coerce+    :: forall a b s. C.Coercible a b+    => BVar s a+    -> BVar s b+coerce = coerceVar+{-# INLINE coerce #-}