Copyright | (c) Justin Le 2018 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
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
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
- data BVar s a
- data W
- backprop :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a)
- evalBP :: (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> b
- gradBP :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> a
- backpropWith :: Num a => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, b -> a)
- evalBP0 :: (forall s. Reifies s W => BVar s a) -> a
- 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))
- evalBP2 :: (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> c
- 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)
- backpropWith2 :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) -> a -> b -> (c, c -> (a, b))
- 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)
- evalBPN :: forall as b. (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> b
- 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
- backpropWithN :: (Every Num as, Known Length as) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, b -> Tuple as)
- class EveryC k c as => Every k (c :: k -> Constraint) (as :: [k])
- constVar :: a -> BVar s a
- auto :: a -> BVar s a
- coerceVar :: Coercible a b => BVar s a -> BVar s b
- (^^.) :: forall b a s. (Num a, Num b, Reifies s W) => BVar s b -> Lens' b a -> BVar s a
- (.~~) :: (Num a, Num b, Reifies s W) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
- (%~~) :: (Num a, Num b, Reifies s W) => Lens' b a -> (BVar s a -> BVar s a) -> BVar s b -> BVar s b
- (^^?) :: forall b a s. (Num b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> Maybe (BVar s a)
- (^^..) :: forall b a s. (Num b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> [BVar s a]
- (^^?!) :: forall b a s. (Num b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> BVar s a
- viewVar :: forall b a s. (Num a, Num b, Reifies s W) => Lens' b a -> BVar s b -> BVar s a
- setVar :: forall a b s. (Num a, Num b, Reifies s W) => Lens' b a -> BVar s a -> BVar s b -> BVar s b
- overVar :: (Num a, Num b, Reifies s W) => Lens' b a -> (BVar s a -> BVar s a) -> BVar s b -> BVar s b
- sequenceVar :: (Traversable t, Num a, Reifies s W) => BVar s (t a) -> t (BVar s a)
- collectVar :: (Foldable t, Functor t, Num a, Reifies s W) => t (BVar s a) -> BVar s (t a)
- previewVar :: forall b a s. (Num b, Num a, Reifies s W) => Traversal' b a -> BVar s b -> Maybe (BVar s a)
- toListOfVar :: forall b a s. (Num b, Num a, Reifies s W) => Traversal' b a -> BVar s b -> [BVar s a]
- isoVar :: (Num a, Reifies s W) => (a -> b) -> (b -> a) -> BVar s a -> BVar s b
- isoVar2 :: (Num a, Num b, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c
- isoVar3 :: (Num a, Num b, Num c, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d
- isoVarN :: (Every Num as, Known Length as, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b
- liftOp :: (Every Num as, Known Length as, Reifies s W) => Op as b -> Prod (BVar s) as -> BVar s b
- liftOp1 :: (Num a, Reifies s W) => Op '[a] b -> BVar s a -> BVar s b
- liftOp2 :: (Num a, Num b, Reifies s W) => Op '[a, b] c -> BVar s a -> BVar s b -> BVar s c
- liftOp3 :: (Num a, Num b, Num c, Reifies s W) => Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d
- newtype Op as a = Op {}
- op0 :: a -> Op '[] a
- opConst :: (Every Num as, Known Length as) => a -> Op as a
- idOp :: Op '[a] a
- opConst' :: Every Num as => Length as -> a -> Op as a
- op1 :: (a -> (b, b -> a)) -> Op '[a] b
- op2 :: (a -> b -> (c, c -> (a, b))) -> Op '[a, b] c
- op3 :: (a -> b -> c -> (d, d -> (a, b, c))) -> Op '[a, b, c] d
- opCoerce :: Coercible a b => Op '[a] b
- opTup :: Op as (Tuple as)
- opIso :: (a -> b) -> (b -> a) -> Op '[a] b
- opIsoN :: (Tuple as -> b) -> (b -> Tuple as) -> Op as b
- opLens :: Num a => Lens' a b -> Op '[a] b
- noGrad1 :: (a -> b) -> Op '[a] b
- noGrad :: (Tuple as -> b) -> Op as b
- data Prod k (f :: k -> *) (a :: [k]) :: forall k. (k -> *) -> [k] -> * where
- pattern (:>) :: forall k (f :: k -> *) (a :: k) (b :: k). f a -> f b -> Prod k f ((:) k a ((:) k b ([] k)))
- only :: f a -> Prod k f ((:) k a ([] k))
- head' :: Prod k f ((:<) k a as) -> f a
- type Tuple = Prod * I
- pattern (::<) :: forall a (as :: [*]). a -> Tuple as -> Tuple ((:<) * a as)
- only_ :: a -> Tuple ((:) * a ([] *))
- newtype I a :: * -> * = I {
- getI :: a
- class Reifies k (s :: k) a | s -> a
Types
A
is a value of type BVar
s aa
that can be "backpropagated".
Functions referring to BVar
s are tracked by the library and can be
automatically differentiated to get their gradients and results.
For simple numeric values, you can use its Num
, Fractional
, and
Floating
instances to manipulate them as if they were the numbers they
represent.
If a
contains items, the items can be accessed and extracted using
lenses. A
can be used to access an Lens'
b aa
inside a b
, using
^^.
(viewVar
):
(^.
) :: a ->Lens'
a b -> b (^^.
) ::BVar
s a ->Lens'
a b ->BVar
s b
There is also ^^?
(previewVar
), to use a Prism'
or Traversal'
to extract a target that may or may not be present
(which can implement pattern matching), ^^..
(toListOfVar
) to use a Traversal'
to extract all
targets inside a BVar
, and .~~
(setVar
) to set and update values
inside a BVar
.
If you have control over your data type definitions, you can also use
splitBV
and joinBV
to manipulate
data types by easily extracting fields out of a BVar
of data types and
creating BVar
s of data types out of BVar
s of their fields. See
Numeric.Backprop for a tutorial on this use pattern.
For more complex operations, libraries can provide functions on BVar
s
using liftOp
and related functions. This is how you
can create primitive functions that users can use to manipulate your
library's values. See
https://backprop.jle.im/08-equipping-your-library.html for a detailed
guide.
For example, the hmatrix library has a matrix-vector multiplication
function, #> :: L m n -> R n -> L m
.
A library could instead provide a function #> ::
, which the user can then use to manipulate their
BVar
(L m n) -> BVar
(R n) -> BVar (R m)BVar
s of L m n
s and R n
s, etc.
See Numeric.Backprop and documentation for
liftOp
for more information.
BVGroup s ([] *) (K1 * i a) (K1 * i (BVar s a)) Source # | |
Eq a => Eq (BVar s a) Source # | Compares the values inside the Since: 0.1.5.0 |
(Floating a, Reifies Type s W) => Floating (BVar s a) Source # | |
(Fractional a, Reifies Type s W) => Fractional (BVar s a) Source # | |
(Num a, Reifies Type s W) => Num (BVar s a) Source # | |
Ord a => Ord (BVar s a) Source # | Compares the values inside the Since: 0.1.5.0 |
NFData a => NFData (BVar s a) Source # | This will force the value inside, as well. |
(Backprop a, Reifies Type s W) => Backprop (BVar s a) Source # | Since: 0.2.2.0 |
Running
backprop :: (Num a, Num b) => (forall s. Reifies s W => BVar s a -> BVar s b) -> a -> (b, a) Source #
backprop
, 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 -> a) Source #
backpropWith
, but with Num
constraints instead of
Backprop
constraints.
See module documentation for Numeric.Backprop.Num for information on using this with tuples.
Note that argument order changed in v0.2.4.
Since: 0.2.0.0
Multiple inputs
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)) Source #
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) Source #
:: (Num a, Num b) | |
=> (forall s. Reifies s W => BVar s a -> BVar s b -> BVar s c) | |
-> a | |
-> b | |
-> (c, c -> (a, b)) | Takes function giving gradient of final result given the output of function |
backpropWith2
, but with Num
constraints instead of
Backprop
constraints.
Note that argument order changed in v0.2.4.
Since: 0.2.0.0
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) Source #
backpropN
, but with Num
constraints instead of
Backprop
constraints.
The
in the constraint says that every value in the
type-level list Every
Num
asas
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
should be fulfilled automatically.Every
Num
as
evalBPN :: forall as b. (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> b Source #
evalBP
generalized to multiple inputs of different types. See
documentation for backpropN
for more details.
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 Source #
backpropWithN :: (Every Num as, Known Length as) => (forall s. Reifies s W => Prod (BVar s) as -> BVar s b) -> Tuple as -> (b, b -> Tuple as) Source #
backpropWithN
, but with Num
constraints instead
of Backprop
constraints.
See backpropN
for information on the Every
constraint.
Note that argument order changed in v0.2.4.
Since: 0.2.0.0
class EveryC k c as => Every k (c :: k -> Constraint) (as :: [k]) #
Manipulating BVar
constVar :: a -> BVar s a Source #
Lift a value into a BVar
representing a constant value.
This value will not be considered an input, and its gradients will not be backpropagated.
coerceVar :: Coercible a b => BVar s a -> BVar s b Source #
Coerce a BVar
contents. Useful for things like newtype wrappers.
Since: 0.1.5.2
(^^.) :: forall b a s. (Num a, Num b, Reifies s W) => BVar s b -> Lens' b a -> BVar s a infixl 8 Source #
(.~~) :: (Num a, Num b, Reifies s W) => Lens' b a -> BVar s a -> BVar s b -> BVar s b infixl 8 Source #
(%~~) :: (Num a, Num b, Reifies s W) => Lens' b a -> (BVar s a -> BVar s a) -> BVar s b -> BVar s b infixr 4 Source #
(^^?) :: forall b a s. (Num b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> Maybe (BVar s a) infixl 8 Source #
^^?
, 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
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 b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> [BVar s a] Source #
(^^?!) :: forall b a s. (Num b, Num a, Reifies s W) => BVar s b -> Traversal' b a -> BVar s a infixl 8 Source #
setVar :: forall a b s. (Num a, Num b, Reifies s W) => Lens' b a -> BVar s a -> BVar s b -> BVar s b Source #
overVar :: (Num a, Num b, Reifies s W) => Lens' b a -> (BVar s a -> BVar s a) -> BVar s b -> BVar s b Source #
sequenceVar :: (Traversable t, Num a, Reifies s W) => BVar s (t a) -> t (BVar s a) Source #
sequenceVar
, but with Num
constraints instead of
Backprop
constraints.
Since v0.2.4, requires a Num
constraint on t a
.
collectVar :: (Foldable t, Functor t, Num a, Reifies s W) => t (BVar s a) -> BVar s (t a) Source #
collectVar
, but with Num
constraints instead of
Backprop
constraints.
Prior to v0.2.3, required a Num
constraint on t a
.
previewVar :: forall b a s. (Num b, Num a, Reifies s W) => Traversal' b a -> BVar s b -> Maybe (BVar s a) Source #
previewVar
, but with Num
constraints instead of
Backprop
constraints.
See documentation for ^^?
for more information and important notes.
toListOfVar :: forall b a s. (Num b, Num a, Reifies s W) => Traversal' b a -> BVar s b -> [BVar s a] Source #
toListOfVar
, but with Num
constraints instead of
Backprop
constraints.
With Isomorphisms
isoVar2 :: (Num a, Num b, Reifies s W) => (a -> b -> c) -> (c -> (a, b)) -> BVar s a -> BVar s b -> BVar s c Source #
isoVar3 :: (Num a, Num b, Num c, Reifies s W) => (a -> b -> c -> d) -> (d -> (a, b, c)) -> BVar s a -> BVar s b -> BVar s c -> BVar s d Source #
isoVarN :: (Every Num as, Known Length as, Reifies s W) => (Tuple as -> b) -> (b -> Tuple as) -> Prod (BVar s) as -> BVar s b Source #
With Op
s
liftOp :: (Every Num as, Known Length as, Reifies s W) => Op as b -> Prod (BVar s) as -> BVar s b Source #
liftOp3 :: (Num a, Num b, Num c, Reifies s W) => Op '[a, b, c] d -> BVar s a -> BVar s b -> BVar s c -> BVar s d Source #
Op
An
describes a differentiable function from Op
as aas
to a
.
For example, a value of type
Op
'[Int, Bool] Double
is a function from an Int
and a Bool
, returning a Double
. It can
be differentiated to give a gradient of an Int
and a Bool
if given
a total derivative for the Double
. If we call Bool
\(2\), then,
mathematically, it is akin to a:
\[ f : \mathbb{Z} \times 2 \rightarrow \mathbb{R} \]
See runOp
, gradOp
, and gradOpWith
for examples on how to run it,
and Op
for instructions on creating it.
It is simpler to not use this type constructor directly, and instead use
the op2
, op1
, op2
, and op3
helper smart constructors.
See Numeric.Backprop.Op for a mini-tutorial on using Prod
and
Tuple
.
To use an Op
with the backprop library, see liftOp
, liftOp1
,
liftOp2
, and liftOp3
.
Op | Construct an See the module documentation for Numeric.Backprop.Op for more
details on the function that this constructor and |
|
(Known [*] (Length *) as, Every * Floating as, Every * Fractional as, Every * Num as, Floating a) => Floating (Op as a) Source # | |
(Known [*] (Length *) as, Every * Fractional as, Every * Num as, Fractional a) => Fractional (Op as a) Source # | |
(Known [*] (Length *) as, Every * Num as, Num a) => Num (Op as a) Source # | |
Creation
opConst :: (Every Num as, Known Length as) => a -> Op as a Source #
An Op
that ignores all of its inputs and returns a given constant
value.
>>>
gradOp' (opConst 10) (1 ::< 2 ::< 3 ::< Ø)
(10, 0 ::< 0 ::< 0 ::< Ø)
opConst' :: Every Num as => Length as -> a -> Op as a Source #
A version of opConst
taking explicit Length
, indicating the
number of inputs and their types.
Requiring an explicit Length
is mostly useful for rare "extremely
polymorphic" situations, where GHC can't infer the type and length of
the the expected input tuple. If you ever actually explicitly write
down as
as a list of types, you should be able to just use
opConst
.
Giving gradients directly
op1 :: (a -> (b, b -> a)) -> Op '[a] b Source #
Create an Op
of a function taking one input, by giving its explicit
derivative. The function should return a tuple containing the result of
the function, and also a function taking the derivative of the result
and return the derivative of the input.
If we have
\[ \eqalign{ f &: \mathbb{R} \rightarrow \mathbb{R}\cr y &= f(x)\cr z &= g(y) } \]
Then the derivative \( \frac{dz}{dx} \), it would be:
\[ \frac{dz}{dx} = \frac{dz}{dy} \frac{dy}{dx} \]
If our Op
represents \(f\), then the second item in the resulting
tuple should be a function that takes \(\frac{dz}{dy}\) and returns
\(\frac{dz}{dx}\).
As an example, here is an Op
that squares its input:
square :: Num a =>Op
'[a] a square =op1
$ \x -> (x*x, \d -> 2 * d * x )
Remember that, generally, end users shouldn't directly construct Op
s;
they should be provided by libraries or generated automatically.
op2 :: (a -> b -> (c, c -> (a, b))) -> Op '[a, b] c Source #
Create an Op
of a function taking two inputs, by giving its explicit
gradient. The function should return a tuple containing the result of
the function, and also a function taking the derivative of the result
and return the derivative of the input.
If we have
\[ \eqalign{ f &: \mathbb{R}^2 \rightarrow \mathbb{R}\cr z &= f(x, y)\cr k &= g(z) } \]
Then the gradient \( \left< \frac{\partial k}{\partial x}, \frac{\partial k}{\partial y} \right> \) would be:
\[ \left< \frac{\partial k}{\partial x}, \frac{\partial k}{\partial y} \right> = \left< \frac{dk}{dz} \frac{\partial z}{dx}, \frac{dk}{dz} \frac{\partial z}{dy} \right> \]
If our Op
represents \(f\), then the second item in the resulting
tuple should be a function that takes \(\frac{dk}{dz}\) and returns
\( \left< \frac{\partial k}{dx}, \frac{\partial k}{dx} \right> \).
As an example, here is an Op
that multiplies its inputs:
mul :: Num a =>Op
'[a, a] a mul =op2'
$ \x y -> (x*y, \d -> (d*y, x*d) )
Remember that, generally, end users shouldn't directly construct Op
s;
they should be provided by libraries or generated automatically.
From Isomorphisms
opTup :: Op as (Tuple as) Source #
An Op
that takes as
and returns exactly the input tuple.
>>>
gradOp' opTup (1 ::< 2 ::< 3 ::< Ø)
(1 ::< 2 ::< 3 ::< Ø, 1 ::< 1 ::< 1 ::< Ø)
opIsoN :: (Tuple as -> b) -> (b -> Tuple as) -> Op as b Source #
An Op
that runs the input value through an isomorphism between
a tuple of values and a value. See opIso
for caveats.
In Numeric.Backprop.Op since version 0.1.2.0, but only exported from Numeric.Backprop since version 0.1.3.0.
Since: 0.1.2.0
No gradients
noGrad1 :: (a -> b) -> Op '[a] b Source #
Create an Op
with no gradient. Can be evaluated with evalOp
, but
will throw a runtime exception when asked for the gradient.
Can be used with BVar
with liftOp1
, and evalBP
will work fine.
gradBP
and backprop
will also work fine if the result is never used
in the final answer, but will throw a runtime exception if the final
answer depends on the result of this operation.
Useful if your only API is exposed through backprop. Just be sure to tell your users that this will explode when finding the gradient if the result is used in the final result.
Since: 0.1.3.0
noGrad :: (Tuple as -> b) -> Op as b Source #
Create an Op
with no gradient. Can be evaluated with evalOp
, but
will throw a runtime exception when asked for the gradient.
Can be used with BVar
with liftOp
, and evalBP
will work fine.
gradBP
and backprop
will also work fine if the result is never used
in the final answer, but will throw a runtime exception if the final
answer depends on the result of this operation.
Useful if your only API is exposed through backprop. Just be sure to tell your users that this will explode when finding the gradient if the result is used in the final result.
Since: 0.1.3.0
Utility
Inductive tuples/heterogeneous lists
data Prod k (f :: k -> *) (a :: [k]) :: forall k. (k -> *) -> [k] -> * where #
Witness ØC ØC (Prod k f (Ø k)) | |
Functor1 k [k] (Prod k) | |
Foldable1 k [k] (Prod k) | |
Traversable1 k [k] (Prod k) | |
IxFunctor1 k [k] (Index k) (Prod k) | |
IxFoldable1 k [k] (Index k) (Prod k) | |
IxTraversable1 k [k] (Index k) (Prod k) | |
TestEquality k f => TestEquality [k] (Prod k f) | |
BoolEquality k f => BoolEquality [k] (Prod k f) | |
Eq1 k f => Eq1 [k] (Prod k f) | |
Ord1 k f => Ord1 [k] (Prod k f) | |
Show1 k f => Show1 [k] (Prod k f) | |
Read1 k f => Read1 [k] (Prod k f) | |
(Known [k] (Length k) as, Every k (Known k f) as) => Known [k] (Prod k f) as | |
(Witness p q (f a2), Witness s t (Prod a1 f as)) => Witness (p, s) (q, t) (Prod a1 f ((:<) a1 a2 as)) | |
ListC ((<$>) * Constraint Eq ((<$>) k * f as)) => Eq (Prod k f as) | |
(ListC ((<$>) * Constraint Eq ((<$>) k * f as)), ListC ((<$>) * Constraint Ord ((<$>) k * f as))) => Ord (Prod k f as) | |
ListC ((<$>) * Constraint Show ((<$>) k * f as)) => Show (Prod k f as) | |
ListC ((<$>) * Constraint Backprop ((<$>) * * f as)) => Backprop (Prod * f as) Source # | |
type WitnessC ØC ØC (Prod k f (Ø k)) | |
type KnownC [k] (Prod k f) as | |
type WitnessC (p, s) (q, t) (Prod a1 f ((:<) a1 a2 as)) | |
pattern (:>) :: forall k (f :: k -> *) (a :: k) (b :: k). f a -> f b -> Prod k f ((:) k a ((:) k b ([] k))) infix 6 #
Construct a two element Prod. Since the precedence of (:>) is higher than (:<), we can conveniently write lists like:
>>>
a :< b :> c
Which is identical to:
>>>
a :< b :< c :< Ø
pattern (::<) :: forall a (as :: [*]). a -> Tuple as -> Tuple ((:<) * a as) infixr 5 #
Cons onto a Tuple.
Misc
class Reifies k (s :: k) a | s -> a #
KnownNat n => Reifies Nat n Integer | |
KnownSymbol n => Reifies Symbol n String | |
Reifies * Z Int | |
Reifies * n Int => Reifies * (D n) Int | |
Reifies * n Int => Reifies * (SD n) Int | |
Reifies * n Int => Reifies * (PD n) Int | |
(B * b0, B * b1, B * b2, B * b3, B * b4, B * b5, B * b6, B * b7, (~) * w0 (W b0 b1 b2 b3), (~) * w1 (W b4 b5 b6 b7)) => Reifies * (Stable w0 w1 a) a | |