backprop-0.2.3.0: doc/04-the-backprop-typeclass.md
---
title: The Backprop Typeclass
---
The Backprop Typeclass
======================
```haskell top hide
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
import GHC.TypeNats
import Numeric.LinearAlgebra.Static (L, R)
import Numeric.Backprop
import Numeric.Backprop.Class
import qualified Data.Vector as V
```
Most of the functions in this module require a `Backprop` constraint on values
you wish to backpropagate. Even if you manage to get around it for the most
part, `gradBP` (the actual function to compute gradients) requires it on both
the inputs and outputs. Let's dig deeper into what it is, and how to define
instances.
The Class
---------
The typeclass contains three methods: `zero`, `add`, and `one`:
```haskell
class Backprop a where
zero :: a -> a
add :: a -> a -> a
one :: a -> a
```
`zero` is "zero" in the verb sense -- it takes a value and "zeroes out" all
components. For a vector, this means returning a zero vector of the same
shape. For a list, this means replacing all of the items with zero and
returning a list of the same length. `one` does the same thing but with one.
`add` is used to add together contributions in gradients, and is usually a
component-wise addition.
Instances are provided for most common data types where it makes sense.
Custom Instances
----------------
### Generics
When defining your own custom types, if your custom type is has *a single
constructor* where all fields are instances of `Backprop`, then *GHC.Generics*
can be used to write your instances automatically:
```haskell top hide
instance Backprop (R n) where
zero = zeroNum
add = addNum
one = oneNum
instance (KnownNat n, KnownNat m) => Backprop (L n m) where
zero = zeroNum
add = addNum
one = oneNum
```
```haskell top
data MyType = MkMyType Double [Float] (R 10) (L 20 10) (V.Vector Double)
deriving Generic
```
Nice type. Since it has a single constructor and all of its fields are already
`Backprop` instances, we can just write:
```haskell top
instance Backprop MyType
```
and now your type can be backpropagated!
### Common Patterns
For writing "primitive" `Backprop` instances (types that aren't product types),
you can use the provided "helpers" from the *Numeric.Backprop.Class* module.
If your type is a `Num` instance, you can use `zeroNum`, `addNum`, and
`oneNum`:
```haskell
instance Backprop Double where
zero = zeroNum
add = addNum
one = oneNum
```
If your type is made using a `Functor` instance, you can use `zeroFunctor` and
`oneFunctor`:
```haskell
instance Backprop a => Backprop (V.Vector a) where
zero = zeroFunctor
add = undefined -- ??
one = oneFunctor
```
And if your type has an `IsList` instance, you can use `addIsList`:
```haskell
instance Backprop a => Backprop (V.Vector a) where
zero = zeroFunctor
add = addIsList
one = oneFunctor
```
### Completely Custom
Completely custom instances are also possible; you just need to implement
`zero`, `add`, and `one` as they make sense for your type. Just make sure that
you obey [the laws][laws] for sane behavior!
[laws]: http://hackage.haskell.org/package/backprop/docs/Numeric-Backprop-Class.html
Moving On
=========
At this point, feel free to **[jump into the haddocks][haddock]**, or read on
further for **[a list of applications and resources][applications]**.
[haddock]: https://hackage.haskell.org/package/backprop
[applications]: https://backprop.jle.im/05-applications.html