diff --git a/Build.hs b/Build.hs
--- a/Build.hs
+++ b/Build.hs
@@ -78,6 +78,8 @@
                   "--package mnist-idx"
                   "--package one-liner-instances"
                   "--package split"
+                  "--package singletons"
+                  "--package mwc-random"
                   "--"
                   ("samples" </> src)
                   "-o" f
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,26 @@
 Changelog
 =========
 
+Version 0.1.3.0
+---------------
+
+*Feb 12, 2018*
+
+<https://github.com/mstksg/backprop/releases/tag/v0.1.3.0>
+
+*   *Preulude.Backprop* module added with lifted versions of several *Prelude*
+    and base functions.
+*   `liftOpX` family of operators now have a more logical ordering for type
+    variables.  This change breaks backwards-compatibility.
+*   `opIsoN` added to export list of *Numeric.Backprop*
+*   `noGrad` and `noGrad1` added to *Numeric.Backprop.Op*, for functions with
+    no defined gradient.
+
+*Internal*
+
+*   Completely decoupled the internal implementation from `Num`, which showed
+    some performance benefits.
+
 Version 0.1.2.0
 ---------------
 
@@ -25,6 +45,9 @@
     *Numeric.Backprop.Tuple*.  This is meant to be a band-aid for the problem
     of orphan instances and potential mismatched tuple types.
 *   Fixed bug in `collectVar` that occurs if container sizes change
+
+*Internal*
+
 *   Internal tweaks to the underlying automatic differentiation types that
     decouple backpropagation from `Num`, internally.  `Num` is now just used
     externally as a part of the API, which might someday be made optional.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,9 +4,10 @@
 [![backprop on Hackage](https://img.shields.io/hackage/v/backprop.svg?maxAge=2592000)](https://hackage.haskell.org/package/backprop)
 [![Build Status](https://travis-ci.org/mstksg/backprop.svg?branch=master)](https://travis-ci.org/mstksg/backprop)
 
-[**Literate Haskell Tutorial/Demo on MNIST data set**][mnist-lhs] (and [PDF
-rendering][mnist-pdf])
+[**Introductory blog post**][blog]
 
+[blog]: https://blog.jle.im/entry/introducing-the-backprop-library.html
+
 Automatic *heterogeneous* back-propagation.
 
 Write your functions to compute your result, and the library will automatically
@@ -27,29 +28,24 @@
 MNIST Digit Classifier Example
 ------------------------------
 
-Tutorial and example on training on the MNIST data set [available here as a
-literate haskell file][mnist-lhs], or [rendered here as a PDF][mnist-pdf]!
-**Read this first!**
+My [blog post][blog] introduces the concepts in this library in the context of
+training a handwritten digit classifier.  I recommend reading that first.
 
+There are some [literate haskell examples][mnist-lhs] in the source, though
+([rendered as pdf here][mnist-pdf]), which can be built (if [stack][] is
+installed) using:
+
 [mnist-lhs]: https://github.com/mstksg/backprop/blob/master/samples/backprop-mnist.lhs
 [mnist-pdf]: https://github.com/mstksg/backprop/blob/master/renders/backprop-mnist.pdf
-
-The [literate haskell file][mnist-lhs] is a standalone haskell file that you
-can compile (preferably with `-O2`) on its own with stack or some other
-dependency manager.  It can also be compiled with the build script in the
-project directory (if [stack][] is installed, and appropriate dependencies are
-installed), using
-
 [stack]: http://haskellstack.org/
 
 ```bash
 $ ./Build.hs exe
 ```
 
-After the MNIST tutorial, there is a follow-up tutorial on using the library
-with more advanced types, with extensible neural networks a la [this blog
-post][blog], [available as literate haskell][neural-lhs] and also [rendered as
-a PDF][neural-pdf].
+There is a follow-up tutorial on using the library with more advanced types,
+with extensible neural networks a la [this blog post][blog], [available as
+literate haskell][neural-lhs] and also [rendered as a PDF][neural-pdf].
 
 [blog]: https://blog.jle.im/entries/series/+practical-dependent-types-in-haskell.html
 [neural-lhs]: https://github.com/mstksg/backprop/blob/master/samples/extensible-neural.lhs
@@ -58,6 +54,8 @@
 Brief example
 -------------
 
+(This is a really brief version of my [blog post][blog])
+
 The quick example below describes the running of a neural network with one
 hidden layer to calculate its squared error with respect to target `targ`,
 which is parameterized by two weight matrices and two bias vectors.
@@ -110,8 +108,8 @@
     -> BVar s (R o)
 neuralNet x n = z
   where
-    y = logistic $ (n ^^. weight1) #>! x + (n ^^. bias1)
-    z = logistic $ (n ^^. weight2) #>! y + (n ^^. bias2)
+    y = logistic $ (n ^^. weight1) #> x + (n ^^. bias1)
+    z = logistic $ (n ^^. weight2) #> y + (n ^^. bias2)
 
 logistic :: Floating a => a -> a
 logistic x = 1 / (1 + exp (-x))
@@ -143,13 +141,10 @@
     -> BVar s (R o)
     -> BVar s (Network i h o)
     -> BVar s Double
-netError x targ n = sum' (err <.>! err)
-  where
-    err = neuralNet x - t
+netError x targ n = norm_2 (neuralNet x - t)
 ```
 
-(`sum'` is a backprop-aware vector sum, and `<.>!` is a backprop-aware dot
-product)
+(`norm_2` is a backprop-aware euclidean norm)
 
 Now, we can perform gradient descent!
 
@@ -167,8 +162,8 @@
 Ta dah!  We were able to compute the gradient of our error function, just by
 only saying how to compute *the error itself*.
 
-For a more fleshed out example, see the [MNIST tutorial][mnist-lhs] (also
-[rendered as a pdf][mnist-pdf])
+For a more fleshed out example, see my [blog post][blog] and the [MNIST
+tutorial][mnist-lhs] (also [rendered as a pdf][mnist-pdf])
 
 Lens Access
 -----------
@@ -292,7 +287,7 @@
 
     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 1`, and `one = fromInteger 1` (a
+    `(<+>) = (+)`, `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`
diff --git a/backprop.cabal b/backprop.cabal
--- a/backprop.cabal
+++ b/backprop.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: d40da486697c0035648b98d75f36ea36bb66bdb648bb3406bf9eed465f497bb2
+-- hash: a179c83822a97b40195355e48510d1b31057e23a68d04abb6966e24bd4b9d6f0
 
 name:           backprop
-version:        0.1.2.0
+version:        0.1.3.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.
@@ -22,6 +22,7 @@
 copyright:      (c) Justin Le 2018
 license:        BSD3
 license-file:   LICENSE
+tested-with:    GHC >= 8.0
 build-type:     Simple
 cabal-version:  >= 1.10
 
@@ -43,7 +44,7 @@
 library
   hs-source-dirs:
       src
-  ghc-options: -Wall -fprint-explicit-kinds -fwarn-redundant-constraints
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints -fprint-explicit-kinds
   build-depends:
       base >=4.7 && <5
     , deepseq
@@ -57,6 +58,7 @@
       Numeric.Backprop
       Numeric.Backprop.Op
       Numeric.Backprop.Tuple
+      Prelude.Backprop
   other-modules:
       Numeric.Backprop.Internal
       Data.Type.Util
@@ -67,7 +69,7 @@
   main-is: MNISTBench.hs
   hs-source-dirs:
       bench
-  ghc-options: -Wall -fprint-explicit-kinds -fwarn-redundant-constraints -threaded -rtsopts -with-rtsopts=-N -O2
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wredundant-constraints -fprint-explicit-kinds -threaded -rtsopts -with-rtsopts=-N -O2
   build-depends:
       backprop
     , base >=4.7 && <5
diff --git a/src/Numeric/Backprop.hs b/src/Numeric/Backprop.hs
--- a/src/Numeric/Backprop.hs
+++ b/src/Numeric/Backprop.hs
@@ -73,7 +73,9 @@
     -- *** Giving gradients directly
   , op1, op2, op3
     -- *** From Isomorphisms
-  , opCoerce, opTup, opIso, opLens
+  , opCoerce, opTup, opIso, opIsoN, opLens
+    -- *** No gradients
+  , noGrad1, noGrad
     -- * Utility
     -- ** Inductive tuples/heterogeneous lists
   , Prod(..), pattern (:>), only, head'
@@ -279,6 +281,9 @@
 -- s a@ (a 'BVar' holding a @a@)
 --
 -- This is the main way to pull out values from 'BVar' of container types.
+--
+-- __WARNING__: Do not use with any lenses that operate "numerically" on
+-- the contents (like 'multiplying').
 --
 (^^.)
     :: forall a b s. (Reifies s W, Num a)
diff --git a/src/Numeric/Backprop/Internal.hs b/src/Numeric/Backprop/Internal.hs
--- a/src/Numeric/Backprop/Internal.hs
+++ b/src/Numeric/Backprop/Internal.hs
@@ -153,17 +153,18 @@
 {-# INLINE forceTapeNode #-}
 
 data SomeTapeNode :: Type where
-    STN :: forall a. Num a
-        => !(TapeNode a)
+    STN :: { _stnZero :: a
+           , _stnNode :: !(TapeNode a)
+           }
         -> SomeTapeNode
 
 forceSomeTapeNode :: SomeTapeNode -> ()
-forceSomeTapeNode (STN tn) = forceTapeNode tn `seq` ()
+forceSomeTapeNode (STN !_ tn) = forceTapeNode tn `seq` ()
 {-# INLINE forceSomeTapeNode #-}
 
 -- | Debugging string for a 'SomeTapeMode'.
 debugSTN :: SomeTapeNode -> String
-debugSTN (STN TN{..}) = show . foldMap1 ((:[]) . debugIR) $ _tnInputs
+debugSTN (STN _ TN{..}) = show . foldMap1 ((:[]) . debugIR) $ _tnInputs
 
 -- | An ephemeral Wengert Tape in the environment.  Used internally to
 -- track of the computational graph of variables.
@@ -184,7 +185,7 @@
     -> IO (BVar s a)
 insertNode tn !x !w = fmap ((`BV` x) . BRIx) . atomicModifyIORef' (wRef w) $ \(!n,!t) ->
     let n' = n + 1
-        t' = STN tn:t
+        t' = STN 0 tn:t
     in  forceTapeNode tn `seq` n' `seq` t' `seq` ((n', t'), n)
 {-# INLINE insertNode #-}
 
@@ -224,7 +225,7 @@
 -- information, and "Numeric.Backprop.Op#prod" for a mini-tutorial on using
 -- 'Prod' and 'Tuple'.
 liftOp
-    :: forall s as b. (Reifies s W, Num b, Every Num as)
+    :: forall as b s. (Reifies s W, Num b, Every Num as)
     => Op as b
     -> Prod (BVar s) as
     -> BVar s b
@@ -232,7 +233,7 @@
 {-# INLINE liftOp #-}
 
 liftOp1_
-    :: forall s a b. (Reifies s W, Num a, Num b)
+    :: forall a b s. (Reifies s W, Num a, Num b)
     => Op '[a] b
     -> BVar s a
     -> IO (BVar s b)
@@ -253,7 +254,7 @@
 -- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more
 -- information.
 liftOp1
-    :: forall s a b. (Reifies s W, Num a, Num b)
+    :: forall a b s. (Reifies s W, Num a, Num b)
     => Op '[a] b
     -> BVar s a
     -> BVar s b
@@ -261,7 +262,7 @@
 {-# INLINE liftOp1 #-}
 
 liftOp2_
-    :: forall s a b c. (Reifies s W, Num a, Num b, Num c)
+    :: forall a b c s. (Reifies s W, Num a, Num b, Num c)
     => Op '[a,b] c
     -> BVar s a
     -> BVar s b
@@ -285,7 +286,7 @@
 -- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more
 -- information.
 liftOp2
-    :: forall s a b c. (Reifies s W, Num a, Num b, Num c)
+    :: forall a b c s. (Reifies s W, Num a, Num b, Num c)
     => Op '[a,b] c
     -> BVar s a
     -> BVar s b
@@ -294,7 +295,7 @@
 {-# INLINE liftOp2 #-}
 
 liftOp3_
-    :: forall s a b c d. (Reifies s W, Num a, Num b, Num c, Num d)
+    :: 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
@@ -321,7 +322,7 @@
 -- See "Numeric.Backprop#liftops" and documentation for 'liftOp' for more
 -- information.
 liftOp3
-    :: forall s a b c d. (Reifies s W, Num a, Num b, Num c, Num d)
+    :: 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
@@ -387,6 +388,12 @@
 
 -- | 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. (Reifies s W, Traversable t, Num a)
     => BVar s (t a)
@@ -395,7 +402,7 @@
 {-# INLINE sequenceVar #-}
 
 collectVar_
-    :: forall a t s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)
+    :: forall t a s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)
     => t (BVar s a)
     -> IO (BVar s (t a))
 collectVar_ !vs = withV (toList vs) $ \(vVec :: Vec n (BVar s a)) -> do
@@ -412,12 +419,18 @@
 -- | 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!
 collectVar
-    :: forall a t s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)
+    :: forall t a s. (Reifies s W, Foldable t, Functor t, Num (t a), Num a)
     => t (BVar s a)
     -> BVar s (t a)
 collectVar !vs = unsafePerformIO $ collectVar_ vs
@@ -478,8 +491,8 @@
     -> m (Runner s)
 initRunner (n, stns) (nx,xs) = do
     delts <- MV.new n
-    for_ (zip [n-1,n-2..] stns) $ \(i, STN (TN{..} :: TapeNode c)) ->
-      MV.write delts i $ unsafeCoerce @c 0
+    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
@@ -498,7 +511,7 @@
     zipWithM_ go [n-1,n-2..] stns
   where
     go :: Int -> SomeTapeNode -> m ()
-    go i (STN TN{..}) = do
+    go i (STN _ TN{..}) = do
       delt <- MV.read _rDelta i
       let gs = _tnGrad (unsafeCoerce delt)
       zipWithPM_ propagate _tnInputs gs
diff --git a/src/Numeric/Backprop/Op.hs b/src/Numeric/Backprop/Op.hs
--- a/src/Numeric/Backprop/Op.hs
+++ b/src/Numeric/Backprop/Op.hs
@@ -51,7 +51,9 @@
   -- ** Giving gradients directly
   , op1, op2, op3
   -- ** From Isomorphisms
-  , opCoerce, opTup, opIso, opLens, opIsoN
+  , opCoerce, opTup, opIso, opIsoN, opLens
+  -- ** No gradient
+  , noGrad1, noGrad
   -- * Manipulation
   , composeOp, composeOp1, (~.)
   , composeOp', composeOp1'
@@ -333,6 +335,40 @@
 opCoerce = opIso coerce coerce
 {-# INLINE opCoerce #-}
 
+-- | 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
+noGrad1 :: (a -> b) -> Op '[a] b
+noGrad1 f = op1 (\x -> (f x, error "noGrad: no gradient defined"))
+{-# INLINE noGrad1 #-}
+
+-- | 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
+noGrad :: (Tuple as -> b) -> Op as b
+noGrad f = Op (\xs -> (f xs, error "noGrads: no gradient defined"))
+{-# INLINE noGrad #-}
+
 -- | An 'Op' that just returns whatever it receives.  The identity
 -- function.
 --
@@ -368,6 +404,9 @@
 -- have derivative 1, so will break for things like
 -- 'Numeric.Lens.exponentiating'.  Basically, don't use this for any
 -- "numeric" isomorphisms.
+--
+-- 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
 opIsoN :: (Tuple as -> b) -> (b -> Tuple as) -> Op as b
diff --git a/src/Prelude/Backprop.hs b/src/Prelude/Backprop.hs
new file mode 100644
--- /dev/null
+++ b/src/Prelude/Backprop.hs
@@ -0,0 +1,214 @@
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- |
+-- Module      : Prelude.Backprop
+-- Copyright   : (c) Justin Le 2018
+-- License     : BSD3
+--
+-- Maintainer  : justin@jle.im
+-- Stability   : experimental
+-- Portability : non-portable
+--
+-- 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.
+--
+-- @since 0.1.3.0
+--
+
+module Prelude.Backprop (
+  -- * Foldable and Traversable
+    sum
+  , product
+  , length
+  , minimum
+  , maximum
+  , traverse
+  -- * Functor and Applicative
+  , fmap
+  , (<$>)
+  , pure
+  , liftA2
+  , liftA3
+  -- * Misc
+  , coerce
+  ) where
+
+import           Numeric.Backprop
+import           Prelude             (Num(..), Fractional(..), Eq(..), Ord(..), Functor, Foldable, Traversable, Applicative, (.), ($))
+import qualified Control.Applicative as P
+import qualified Data.Coerce         as C
+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'.  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.
+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.
+--
+-- 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)
+    => (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.
+--
+-- 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)
+    => (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.
+--
+-- 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)
+       , 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.
+--
+-- 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)
+       , 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, Num a, Num b, Reifies s W)
+    => BVar s a
+    -> BVar s b
+coerce = liftOp1 $ opIso C.coerce C.coerce
+{-# INLINE coerce #-}
