diff --git a/src/Data/Derivative.hs b/src/Data/Derivative.hs
--- a/src/Data/Derivative.hs
+++ b/src/Data/Derivative.hs
@@ -15,8 +15,9 @@
 
 module Data.Derivative
   (
-    (:>)(..), (:~>), dZero, dConst, dId
-  , linearD, bilinearD
+    (:>)(..), (:~>), dZero, dConst
+  , idD, fstD, sndD
+  , linearD, distribD
   , (@.), (>-<)
   ) where
 
@@ -48,14 +49,10 @@
 -- with the restriction that the a :~> b is linear
 
 instance Functor ((:>) a) where
-  fmap f (D b b') = D (f b) (f `onDer` b')
+  fmap f (D b b') = D (f b) ((fmap.fmap) f b')
 
 -- I think fmap will be meaningful only with *linear* functions.
 
--- Lift a function to act on values inside of derivative towers
-onDer :: (b -> c) -> (a :~> b) -> (a :~> c)
-onDer = fmap.fmap
-
 -- Handy for missing methods.
 noOv :: String -> a
 noOv op = error (op ++ ": not defined on a :> b")
@@ -78,10 +75,10 @@
 dZero :: VectorSpace b s => a:>b
 dZero = dConst zeroV
 
--- | Tower of derivatives of the identity function.  Sometimes called "the
+-- | Differentiable identity function.  Sometimes called "the
 -- derivation variable" or similar, but it's not really a variable.
-dId :: VectorSpace v s => v -> v:>v
-dId = linearD id
+idD :: VectorSpace u s => u :~> u
+idD = linearD id
 
 -- or
 --   dId v = D v dConst
@@ -91,23 +88,41 @@
 linearD :: VectorSpace v s => (u :-* v) -> (u :~> v)
 linearD f u = D (f u) (dConst . f)
 
--- | Derivative tower for applying a bilinear function, such as
--- multiplication.
-bilinearD :: VectorSpace w s =>
-             (u -> v -> w) -> (t :> u) -> (t :> v) -> (t :> w)
-bilinearD op (D s s') (D u u') =
-  D (s `op` u) ((s `op`) `onDer` u' ^+^ (`op` u) `onDer` s')
 
+-- Other examples of linear functions
+
+-- | Differentiable version of 'fst'
+fstD :: VectorSpace a s => (a,b) :~> a
+fstD = linearD fst
+
+-- | Differentiable version of 'snd'
+sndD :: VectorSpace b s => (a,b) :~> b
+sndD = linearD snd
+
+-- | Derivative tower for applying a binary function that distributes over
+-- addition, such as multiplication.
+distribD :: (VectorSpace u s) =>
+             (b -> c -> u) -> ((a :> b) -> (a :> c) -> (a :> u))
+          -> (a :> b) -> (a :> c) -> (a :> u)
+distribD op opD u@(D u0 u') v@(D v0 v') =
+  D (u0 `op` v0) ((u `opD`) . v' ^+^ (`opD` v) . u')
+
+-- Equivalently,
+-- 
+--   distribD op opD u@(D u0 u') v@(D v0 v') =
+--     D (u0 `op` v0) (\ da -> (u `opD` v' da) ^+^ (u' da `opD` v))
+
+
 -- I'm not sure about the next three, which discard information
 instance Show b => Show (a :> b) where show    = noOv "show"
 instance Eq   b => Eq   (a :> b) where (==)    = noOv "(==)"
 instance Ord  b => Ord  (a :> b) where compare = noOv "compare"
 
 instance VectorSpace u s => VectorSpace (a :> u) (a :> s) where
-  zeroV   = dConst    zeroV    -- or dZero
-  (*^)    = bilinearD (*^)
-  negateV = fmap      negateV
-  (^+^)   = liftA2    (^+^)
+  zeroV   = dConst   zeroV    -- or dZero
+  (*^)    = distribD (*^) (*^)
+  negateV = fmap     negateV
+  (^+^)   = liftA2   (^+^)
 
 -- | Chain rule.
 (@.) :: (b :~> c) -> (a :~> b) -> (a :~> c)
@@ -118,17 +133,20 @@
 
 
 -- | Specialized chain rule.
-(>-<) :: VectorSpace b s => (b -> b) -> ((a :> b) -> (a :> s))
-      -> (a :> b) -> (a :> b)
-f >-< f' = \ b@(D b0 b') -> D (f b0) ((f' b *^) . b')
+(>-<) :: VectorSpace u s => (u -> u) -> ((a :> u) -> (a :> s))
+      -> (a :> u) -> (a :> u)
 
+f >-< f' = \ u@(D u0 u') -> D (f u0) ((f' u *^) . u')
 
+-- Equivalently:
+-- 
+--   f >-< f' = \ u@(D u0 u') -> D (f u0) (\ da -> f' u *^ u' da)
+
 instance (Num b, VectorSpace b b) => Num (a:>b) where
   fromInteger = dConst . fromInteger
-  (+) = liftA2    (+)
-  (-) = liftA2    (-)
-  (*) = bilinearD (*)
-  
+  (+) = liftA2   (+)
+  (-) = liftA2   (-)
+  (*) = distribD (*) (*)
   negate = negate >-< -1
   abs    = abs    >-< signum
   signum = signum >-< 0  -- derivative wrong at zero
diff --git a/src/Data/VectorSpace.hs b/src/Data/VectorSpace.hs
--- a/src/Data/VectorSpace.hs
+++ b/src/Data/VectorSpace.hs
@@ -156,9 +156,9 @@
 -- Standard instance for an applicative functor applied to a vector space.
 instance VectorSpace v s => VectorSpace (a->v) s where
   zeroV   = pure   zeroV
-  (*^) s  = fmap (s *^)
+  (*^) s  = fmap   (s *^)
   (^+^)   = liftA2 (^+^)
-  negateV = fmap negateV
+  negateV = fmap   negateV
 
 -- I don't know how to make the InnerSpace class work out, because the
 -- inner product would have to combine two vector *functions* into a
diff --git a/vector-space.cabal b/vector-space.cabal
--- a/vector-space.cabal
+++ b/vector-space.cabal
@@ -1,5 +1,5 @@
 Name:                vector-space
-Version:             0.1.1
+Version:             0.1.2
 Synopsis: 	     Vector & affine spaces, plus derivatives
 Category:            math
 Description:
