diff --git a/linear.cabal b/linear.cabal
--- a/linear.cabal
+++ b/linear.cabal
@@ -1,6 +1,6 @@
 name:          linear
 category:      Math, Algebra
-version:       0.5
+version:       0.6
 license:       BSD3
 cabal-version: >= 1.8
 license-file:  LICENSE
@@ -31,13 +31,12 @@
 library
   build-depends:
     base             >= 4.5 && < 5,
-    distributive     >= 0.2.2,
-    lens             >= 3.6 && < 3.8,
-    template-haskell >= 2.7 && < 2.9
+    distributive     >= 0.2.2
 
   exposed-modules:
     Linear
     Linear.Conjugate
+    Linear.Core
     Linear.Epsilon
     Linear.Matrix
     Linear.Metric
@@ -59,7 +58,10 @@
     base,
     directory >= 1.0 && < 1.2,
     doctest   >= 0.8 && < 0.10,
-    filepath  >= 1.3 && < 1.4
+    filepath  >= 1.3 && < 1.4,
+    lens      >= 3.7,
+    simple-reflect >= 0.3.1
+
   ghc-options: -Wall -Werror -threaded
   hs-source-dirs: tests
 
diff --git a/src/Linear.hs b/src/Linear.hs
--- a/src/Linear.hs
+++ b/src/Linear.hs
@@ -13,6 +13,7 @@
 ----------------------------------------------------------------------------
 module Linear
   ( module Linear.Conjugate
+  , module Linear.Core
   , module Linear.Epsilon
   , module Linear.Matrix
   , module Linear.Metric
@@ -25,6 +26,7 @@
   )  where
 
 import Linear.Conjugate
+import Linear.Core
 import Linear.Epsilon
 import Linear.Matrix
 import Linear.Metric
@@ -34,3 +36,5 @@
 import Linear.V3
 import Linear.V4
 import Linear.Vector
+
+{-# ANN module "Hlint: ignore Use import/export shortcut" #-}
diff --git a/src/Linear/Conjugate.hs b/src/Linear/Conjugate.hs
--- a/src/Linear/Conjugate.hs
+++ b/src/Linear/Conjugate.hs
@@ -15,13 +15,32 @@
   ) where
 
 import Data.Complex hiding (conjugate)
+import Data.Int
+import Data.Word
 
 -- | An involutive ring
 class Num a => Conjugate a where
   -- | Conjugate a value. This defaults to the trivial involution.
+  --
+  -- >>> conjugate (1 :+ 2)
+  -- 1.0 :+ (-2.0)
+  --
+  -- >>> conjugate 1
+  -- 1
   conjugate :: a -> a
   conjugate = id
 
+instance Conjugate Integer
+instance Conjugate Int
+instance Conjugate Int64
+instance Conjugate Int32
+instance Conjugate Int16
+instance Conjugate Int8
+instance Conjugate Word
+instance Conjugate Word64
+instance Conjugate Word32
+instance Conjugate Word16
+instance Conjugate Word8
 instance Conjugate Double
 instance Conjugate Float
 instance (Conjugate a, RealFloat a) => Conjugate (Complex a) where
diff --git a/src/Linear/Core.hs b/src/Linear/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Linear/Core.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE RankNTypes #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Linear.Core
+-- Copyright   :  (C) 2012-2013 Edward Kmett,
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Corepresentable functors as vector spaces
+----------------------------------------------------------------------------
+module Linear.Core
+  ( Core(..)
+  ) where
+
+-- |
+-- A 'Functor' @f@ is corepresentable if it is isomorphic to @(x -> a)@
+-- for some x. Nearly all such functors can be represented by choosing @x@ to be
+-- the set of lenses that are polymorphic in the contents of the 'Functor',
+-- that is to say @x = 'Rep' f@ is a valid choice of 'x' for (nearly) every
+-- 'Representable' 'Functor'.
+class Functor f => Core f where
+  core :: ((forall g x. Functor g => (x -> g x) -> f x -> g (f x)) -> a) -> f a
diff --git a/src/Linear/Epsilon.hs b/src/Linear/Epsilon.hs
--- a/src/Linear/Epsilon.hs
+++ b/src/Linear/Epsilon.hs
@@ -14,6 +14,18 @@
   ) where
 
 -- | Provides a fairly subjective test to see if a quantity is near zero.
+--
+-- >>> nearZero (1e-11 :: Double)
+-- False
+--
+-- >>> nearZero (1e-17 :: Double)
+-- True
+--
+-- >>> nearZero (1e-5 :: Float)
+-- False
+--
+-- >>> nearZero (1e-7 :: Float)
+-- True
 class Num a => Epsilon a where
   -- | Determine if a quantity is near zero.
   nearZero :: a -> Bool
diff --git a/src/Linear/Matrix.hs b/src/Linear/Matrix.hs
--- a/src/Linear/Matrix.hs
+++ b/src/Linear/Matrix.hs
@@ -23,7 +23,7 @@
   ) where
 
 import Control.Applicative
-import Control.Lens
+import Control.Monad (join)
 import Data.Distributive
 import Data.Foldable as Foldable
 import Linear.Epsilon
@@ -35,49 +35,81 @@
 import Linear.Vector ((*^))
 import Linear.Conjugate
 
+-- $setup
+-- >>> import Data.Complex
+-- >>> import Debug.SimpleReflect.Vars
+
 infixl 7 !*!
--- | matrix product
+-- | Matrix product
+--
+-- >>> V2 (V3 1 2 3) (V3 4 5 6) !*! V3 (V2 1 2) (V2 3 4) (V2 4 5)
+-- V2 (V2 19 25) (V2 43 58)
 (!*!) :: (Functor m, Foldable r, Applicative r, Distributive n, Num a) => m (r a) -> r (n a) -> m (n a)
-f !*! g = fmap (\r -> Foldable.foldr (+) 0 . liftA2 (*) r <$> g') f
+f !*! g = fmap (\r -> Foldable.sum . liftA2 (*) r <$> g') f
   where g' = distribute g
 
--- | matrix * column vector
+-- | Matrix * column vector
+--
+-- >>> V2 (V3 1 2 3) (V3 4 5 6) !* V3 7 8 9
+-- V2 50 122
 infixl 7 *!
 (!*) :: (Functor m, Metric r, Num a) => m (r a) -> r a -> m a
 m !* v = dot v <$> m
 
 infixl 7 !*
--- | row vector * matrix
+
+-- | Row vector * matrix
+--
+-- >>> V2 1 2 *! V2 (V3 3 4 5) (V3 6 7 8)
+-- V3 15 18 21
 (*!) :: (Metric r, Distributive n, Num a) => r a -> r (n a) -> n a
 f *! g = dot f <$> distribute g
 
 infixl 7 *!!
--- |Scalar-matrix product.
+-- | Scalar-matrix product
+--
+-- >>> 5 *!! V2 (V2 1 2) (V2 3 4)
+-- V2 (V2 5 10) (V2 15 20)
 (*!!) :: (Functor m, Functor r, Num a) => a -> m (r a) -> m (r a)
 s *!! m = fmap (s *^) m
 {-# INLINE (*!!) #-}
 
 infixl 7 !!*
--- |Matrix-scalar product.
+-- | Matrix-scalar product
+--
+-- >>> V2 (V2 1 2) (V2 3 4) !!* 5
+-- V2 (V2 5 10) (V2 15 20)
 (!!*) :: (Functor m, Functor r, Num a) => m (r a) -> a -> m (r a)
 (!!*) = flip (*!!)
 {-# INLINE (!!*) #-}
 
-
--- | hermitian conjugate or conjugate transpose
+-- | Hermitian conjugate or conjugate transpose
+--
+-- >>> adjoint (V2 (V2 (1 :+ 2) (3 :+ 4)) (V2 (5 :+ 6) (7 :+ 8)))
+-- V2 (V2 (1.0 :+ (-2.0)) (5.0 :+ (-6.0))) (V2 (3.0 :+ (-4.0)) (7.0 :+ (-8.0)))
 adjoint :: (Functor m, Distributive n, Conjugate a) => m (n a) -> n (m a)
 adjoint = collect (fmap conjugate)
 {-# INLINE adjoint #-}
 
 -- | Compute the trace of a matrix
+--
+-- >>> trace (V2 (V2 a b) (V2 c d))
+-- a + d
 trace :: (Monad f, Foldable f, Num a) => f (f a) -> a
-trace m = Foldable.sum (m >>= id)
+trace m = Foldable.sum (join m)
 {-# INLINE trace #-}
 
--- | Matrices use a row-major representation.
+-- * Matrices
+--
+-- Matrices use a row-major representation.
+
+-- | A 2x2 matrix with row-major representation
 type M22 a = V2 (V2 a)
+-- | A 3x3 matrix with row-major representation
 type M33 a = V3 (V3 a)
+-- | A 4x4 matrix with row-major representation
 type M44 a = V4 (V4 a)
+-- | A 4x3 matrix with row-major representation
 type M43 a = V4 (V3 a)
 
 -- | Build a rotation matrix from a unit 'Quaternion'.
@@ -92,70 +124,99 @@
 
 mkTransformationMat :: Num a => M33 a -> V3 a -> M44 a
 mkTransformationMat (V3 r1 r2 r3) (V3 tx ty tz) =
-  V4 (snoc3 r1 tx) (snoc3 r2 ty) (snoc3 r3 tz) (set _w 1 0)
-  where snoc3 (V3 x y z) w = V4 x y z w
+  V4 (snoc3 r1 tx) (snoc3 r2 ty) (snoc3 r3 tz) (V4 0 0 0 1)
+  where snoc3 (V3 x y z) = V4 x y z
 
 -- |Build a transformation matrix from a rotation expressed as a
 -- 'Quaternion' and a translation vector.
 mkTransformation :: Num a => Quaternion a -> V3 a -> M44 a
 mkTransformation = mkTransformationMat . fromQuaternion
 
+-- | Convert from a 4x3 matrix to a 4x4 matrix, extending it with the @[ 0 0 0 1 ]@ column vector
 m43_to_m44 :: Num a => M43 a -> M44 a
 m43_to_m44
   (V4 (V3 a b c)
       (V3 d e f)
       (V3 g h i)
       (V3 j k l)) =
-  (V4 (V4 a b c 0)
-      (V4 d e f 0)
-      (V4 g h i 0)
-      (V4 j k l 1))
+  V4 (V4 a b c 0)
+     (V4 d e f 0)
+     (V4 g h i 0)
+     (V4 j k l 1)
+{-# ANN m43_to_m44 "HLint: ignore Use camelCase" #-}
 
+-- | Convert a 3x3 matrix to a 4x4 matrix extending it with 0's in the new row and column.
 m33_to_m44 :: Num a => M33 a -> M44 a
 m33_to_m44 (V3 r1 r2 r3) = V4 (vector r1) (vector r2) (vector r3) (point 0)
+{-# ANN m33_to_m44 "HLint: ignore Use camelCase" #-}
 
 -- |3x3 identity matrix.
+--
+-- >>> eye3
+-- V3 (V3 1 0 0) (V3 0 1 0) (V3 0 0 1)
 eye3 :: Num a => M33 a
-eye3 = V3 (set _x 1 0) (set _y 1 0) (set _z 1 0)
+eye3 = V3 (V3 1 0 0)
+          (V3 0 1 0)
+          (V3 0 0 1)
 
 -- |4x4 identity matrix.
+--
+-- >>> eye4
+-- V4 (V4 1 0 0 0) (V4 0 1 0 0) (V4 0 0 1 0) (V4 0 0 0 1)
 eye4 :: Num a => M44 a
-eye4 = V4 (set _x 1 0) (set _y 1 0) (set _z 1 0) (set _w 1 0)
+eye4 = V4 (V4 1 0 0 0)
+          (V4 0 1 0 0)
+          (V4 0 0 1 0)
+          (V4 0 0 0 1)
 
+
 -- |Extract the translation vector (first three entries of the last
 -- column) from a 3x4 or 4x4 matrix
 translation :: (R3 t, R4 v, Functor f, Functor t) => (V3 a -> f (V3 a)) -> t (v a) -> f (t a)
-translation = (. fmap (^._w)) . _xyz
+translation = (. fmap (^._w)) . _xyz where
+  x ^. l = getConst (l Const x)
 
 -- |2x2 matrix determinant.
-det22 :: Num a => V2 (V2 a) -> a
+--
+-- >>> det22 (V2 (V2 a b) (V2 c d))
+-- a * d - b * c
+det22 :: Num a => M22 a -> a
 det22 (V2 (V2 a b) (V2 c d)) = a * d - b * c
 {-# INLINE det22 #-}
 
 -- |3x3 matrix determinant.
-det33 :: Num a => V3 (V3 a) -> a
+--
+-- >>> det33 (V3 (V3 a b c) (V3 d e f) (V3 g h i))
+-- a * (e * i - f * h) - d * (b * i - c * h) + g * (b * f - c * e)
+det33 :: Num a => M33 a -> a
 det33 (V3 (V3 a b c)
           (V3 d e f)
           (V3 g h i)) = a * (e*i-f*h) - d * (b*i-c*h) + g * (b*f-c*e)
 {-# INLINE det33 #-}
 
 -- |2x2 matrix inverse.
+--
+-- >>> inv22 $ V2 (V2 1 2) (V2 3 4)
+-- Just (V2 (V2 (-2.0) 1.0) (V2 1.5 (-0.5)))
 inv22 :: (Epsilon a, Floating a) => M22 a -> Maybe (M22 a)
 inv22 m@(V2 (V2 a b) (V2 c d))
   | nearZero det = Nothing
-  | otherwise = Just $ (1 / det) *!! (V2 (V2 d (-b)) (V2 (-c) a))
+  | otherwise = Just $ (1 / det) *!! V2 (V2 d (-b)) (V2 (-c) a)
   where det = det22 m
 {-# INLINE inv22 #-}
 
 -- |3x3 matrix inverse.
+--
+-- >>> inv33 $ V3 (V3 1 2 4) (V3 4 2 2) (V3 1 1 1)
+-- Just (V3 (V3 0.0 0.5 (-1.0)) (V3 (-0.5) (-0.75) 3.5) (V3 0.5 0.25 (-1.5)))
 inv33 :: (Epsilon a, Floating a) => M33 a -> Maybe (M33 a)
 inv33 m@(V3 (V3 a b c)
             (V3 d e f)
             (V3 g h i))
   | nearZero det = Nothing
-  | otherwise = Just $ (1 / det) *!! (V3 (V3 a' b' c')
-                                         (V3 d' e' f')
-                                         (V3 g' h' i'))
+  | otherwise = Just $ (1 / det) *!! V3 (V3 a' b' c')
+                                        (V3 d' e' f')
+                                        (V3 g' h' i')
   where a' = cofactor (e,f,h,i)
         b' = cofactor (c,b,i,h)
         c' = cofactor (b,c,e,f)
diff --git a/src/Linear/Metric.hs b/src/Linear/Metric.hs
--- a/src/Linear/Metric.hs
+++ b/src/Linear/Metric.hs
@@ -17,10 +17,17 @@
 import Control.Applicative
 import Linear.Epsilon
 
+-- $setup
+-- >>> import Linear
+
 -- | A free inner product/metric space
 class Applicative f => Metric f where
   -- | Compute the inner product of two vectors or (equivalently)
   -- convert a vector @f a@ into a covector @f a -> a@.
+  --
+  -- >>> V2 1 2 `dot` V2 3 4
+  -- 11
+
   dot :: Num a => f a -> f a -> a
 
   -- | Compute the squared norm. The name quadrance arises from
diff --git a/src/Linear/Plucker.hs b/src/Linear/Plucker.hs
--- a/src/Linear/Plucker.hs
+++ b/src/Linear/Plucker.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Linear.Plucker
@@ -17,6 +18,11 @@
   , (><)
   , plucker
   , intersects
+  -- * Basis elements
+  ,      p01, p02, p03
+  , p10,      p12, p13
+  , p20, p21,      p23
+  , p30, p31, p32
   ) where
 
 import Control.Applicative
@@ -24,10 +30,12 @@
 import Data.Foldable as Foldable
 import Data.Monoid
 import Data.Traversable
-import Linear.Epsilon
+import Foreign.Ptr (castPtr)
+import Foreign.Storable (Storable(..))
 import GHC.Arr (Ix(..))
+import Linear.Core
+import Linear.Epsilon
 import Linear.Metric
-import Control.Lens
 import Linear.V4
 
 -- | Plücker coordinates for lines in a 3-dimensional space.
@@ -47,16 +55,27 @@
 instance Monad Plucker where
   return a = Plucker a a a a a a
   {-# INLINE return #-}
-  (>>=) = bindRep
+  Plucker a b c d e f >>= g = Plucker a' b' c' d' e' f' where
+    Plucker a' _ _ _ _ _ = g a
+    Plucker _ b' _ _ _ _ = g b
+    Plucker _ _ c' _ _ _ = g c
+    Plucker _ _ _ d' _ _ = g d
+    Plucker _ _ _ _ e' _ = g e
+    Plucker _ _ _ _ _ f' = g f
   {-# INLINE (>>=) #-}
 
 instance Distributive Plucker where
-  distribute = distributeRep
+  distribute f = Plucker (fmap (\(Plucker x _ _ _ _ _) -> x) f)
+                         (fmap (\(Plucker _ x _ _ _ _) -> x) f)
+                         (fmap (\(Plucker _ _ x _ _ _) -> x) f)
+                         (fmap (\(Plucker _ _ _ x _ _) -> x) f)
+                         (fmap (\(Plucker _ _ _ _ x _) -> x) f)
+                         (fmap (\(Plucker _ _ _ _ _ x) -> x) f)
   {-# INLINE distribute #-}
 
-instance Representable Plucker where
-  rep f = Plucker (f p01) (f p02) (f p03) (f p23) (f p31) (f p12)
-  {-# INLINE rep #-}
+instance Core Plucker where
+  core f = Plucker (f p01) (f p02) (f p03) (f p23) (f p31) (f p12)
+  {-# INLINE core #-}
 
 instance Foldable Plucker where
   foldMap g (Plucker a b c d e f) =
@@ -84,8 +103,8 @@
     unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
     unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
     unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-    unsafeIndex (l1,u1) i1)))))
+    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) *
+    unsafeIndex (l1,u1) i1))))
   {-# INLINE unsafeIndex #-}
 
   inRange (Plucker l1 l2 l3 l4 l5 l6,Plucker u1 u2 u3 u4 u5 u6) (Plucker i1 i2 i3 i4 i5 i6) =
@@ -118,6 +137,29 @@
   fromRational = pure . fromRational
   {-# INLINE fromRational #-}
 
+instance Storable a => Storable (Plucker a) where
+  sizeOf _ = 6 * sizeOf (undefined::a)
+  {-# INLINE sizeOf #-}
+  alignment _ = alignment (undefined::a)
+  {-# INLINE alignment #-}
+  poke ptr (Plucker a b c d e f) = do
+    poke ptr' a
+    pokeElemOff ptr' 1 b
+    pokeElemOff ptr' 2 c
+    pokeElemOff ptr' 3 d
+    pokeElemOff ptr' 4 e
+    pokeElemOff ptr' 5 f
+    where ptr' = castPtr ptr
+  {-# INLINE poke #-}
+  peek ptr = Plucker <$> peek ptr'
+                     <*> peekElemOff ptr' 1
+                     <*> peekElemOff ptr' 2
+                     <*> peekElemOff ptr' 3
+                     <*> peekElemOff ptr' 4
+                     <*> peekElemOff ptr' 5
+    where ptr' = castPtr ptr
+  {-# INLINE peek #-}
+
 -- | Given a pair of points represented by homogeneous coordinates generate Plücker coordinates
 -- for the line through them.
 plucker :: Num a => V4 a -> V4 a -> Plucker a
@@ -145,6 +187,24 @@
 {-# INLINE p23 #-}
 {-# INLINE p31 #-}
 {-# INLINE p12 #-}
+
+-- | These elements form an alternate basis for the Plücker space, or the Grassmanian manifold @Gr(2,V4)@.
+p10, p20, p30, p32, p13, p21 :: (Functor f, Num a) => (a -> f a) -> Plucker a -> f (Plucker a)
+p10 = anti p01
+p20 = anti p02
+p30 = anti p03
+p32 = anti p23
+p13 = anti p31
+p21 = anti p21
+{-# INLINE p10 #-}
+{-# INLINE p20 #-}
+{-# INLINE p30 #-}
+{-# INLINE p32 #-}
+{-# INLINE p13 #-}
+{-# INLINE p21 #-}
+
+anti :: (Functor f, Num a) => ((a -> f a) -> r) -> (a -> f a) -> r
+anti k f = k (fmap negate . f . negate)
 
 -- | Valid Plücker coordinates @p@ will have @'squaredError' p '==' 0@
 --
diff --git a/src/Linear/Quaternion.hs b/src/Linear/Quaternion.hs
--- a/src/Linear/Quaternion.hs
+++ b/src/Linear/Quaternion.hs
@@ -27,17 +27,19 @@
   , rotate
   , axisAngle
   ) where
+
 import Control.Applicative
-import Control.Lens
 import Data.Complex (Complex((:+)))
 import Data.Data
 import Data.Distributive
+import Data.Traversable
 import Data.Foldable
 import GHC.Arr (Ix(..))
 import qualified Data.Foldable as F
 import Data.Monoid
 import Foreign.Ptr (castPtr, plusPtr)
 import Foreign.Storable (Storable(..))
+import Linear.Core
 import Linear.Epsilon
 import Linear.Conjugate
 import Linear.Metric
@@ -45,6 +47,7 @@
 import Linear.Vector
 import Prelude hiding (any)
 
+-- | Quaternions
 data Quaternion a = Quaternion a {-# UNPACK #-}!(V3 a)
                     deriving (Eq,Ord,Read,Show,Data,Typeable)
 
@@ -63,7 +66,12 @@
 instance Monad Quaternion where
   return = pure
   {-# INLINE return #-}
-  (>>=) = bindRep -- the diagonal of a sedenion is super useful!
+  -- the diagonal of a sedenion is super useful!
+  Quaternion a (V3 b c d) >>= f = Quaternion a' (V3 b' c' d') where
+    Quaternion a' _          = f a
+    Quaternion _ (V3 b' _ _) = f b
+    Quaternion _ (V3 _ c' _) = f c
+    Quaternion _ (V3 _ _ d') = f d
   {-# INLINE (>>=) #-}
 
 instance Ix a => Ix (Quaternion a) where
@@ -81,9 +89,9 @@
       inRange (l1,u1) i1 && inRange (l2,u2) i2
     {-# INLINE inRange #-}
 
-instance Representable Quaternion where
-  rep f = Quaternion (f _e) (V3 (f _i) (f _j) (f _k))
-  {-# INLINE rep #-}
+instance Core Quaternion where
+  core f = Quaternion (f _e) (V3 (f _i) (f _j) (f _k))
+  {-# INLINE core #-}
 
 instance Foldable Quaternion where
   foldMap f (Quaternion e v) = f e `mappend` foldMap f v
@@ -95,7 +103,7 @@
   traverse f (Quaternion e v) = Quaternion <$> f e <*> traverse f v
   {-# INLINE traverse #-}
 
-instance forall a. Storable a => Storable (Quaternion a) where
+instance Storable a => Storable (Quaternion a) where
   sizeOf _ = 4 * sizeOf (undefined::a)
   {-# INLINE sizeOf #-}
   alignment _ = alignment (undefined::a)
@@ -170,6 +178,7 @@
   Quaternion e v `dot` Quaternion e' v' = e*e' + (v `dot` v')
   {-# INLINE dot #-}
 
+-- | A vector space that includes the basis elements '_e' and '_i'
 class Complicated t where
   _e :: Functor f => (a -> f a) -> t a -> f (t a)
   _i :: Functor f => (a -> f a) -> t a -> f (t a)
@@ -181,11 +190,12 @@
   {-# INLINE _i #-}
 
 instance Complicated Quaternion where
-  _e f (Quaternion a v) = (\a' -> Quaternion a' v) <$> f a
+  _e f (Quaternion a v) = (`Quaternion` v) <$> f a
   {-# INLINE _e #-}
   _i f (Quaternion a v) = Quaternion a <$> _x f v
   {-# INLINE _i #-}
 
+-- | A vector space that includes the basis elements '_e', '_i', '_j' and '_k'
 class Complicated t => Hamiltonian t where
   _j :: Functor f => (a -> f a) -> t a -> f (t a)
   _k :: Functor f => (a -> f a) -> t a -> f (t a)
@@ -200,7 +210,10 @@
   {-# INLINE _ijk #-}
 
 instance Distributive Quaternion where
-  distribute = distributeRep
+  distribute f = Quaternion (fmap (\(Quaternion x _) -> x) f) $ V3
+    (fmap (\(Quaternion _ (V3 y _ _)) -> y) f)
+    (fmap (\(Quaternion _ (V3 _ z _)) -> z) f)
+    (fmap (\(Quaternion _ (V3 _ _ w)) -> w) f)
   {-# INLINE distribute #-}
 
 instance (Conjugate a, RealFloat a) => Conjugate (Quaternion a) where
@@ -292,25 +305,25 @@
     where qiq = qi q
   {-# INLINE tanh #-}
 
-  asin q = cut asin q
+  asin = cut asin
   {-# INLINE asin #-}
-  acos q = cut acos q
+  acos = cut acos
   {-# INLINE acos #-}
-  atan q = cut atan q
+  atan = cut atan
   {-# INLINE atan #-}
 
-  asinh q = cut asinh q
+  asinh = cut asinh
   {-# INLINE asinh #-}
-  acosh q = cut acosh q
+  acosh = cut acosh
   {-# INLINE acosh #-}
-  atanh q = cut atanh q
+  atanh = cut atanh
   {-# INLINE atanh #-}
 
 
 -- | Helper for calculating with specific branch cuts
 cut :: RealFloat a => (Complex a -> Complex a) -> Quaternion a -> Quaternion a
-cut f q@(Quaternion e v)
-  | qiq == 0 = Quaternion a (_x.~b$v)
+cut f q@(Quaternion e (V3 _ y z))
+  | qiq == 0 = Quaternion a (V3 b y z)
   | otherwise = reimagine a (b / ai) q
   where qiq = qi q
         ai = sqrt qiq
@@ -387,7 +400,8 @@
 
 -- | Apply a rotation to a vector.
 rotate :: (Conjugate a, RealFloat a) => Quaternion a -> V3 a -> V3 a
-rotate q v = (q * Quaternion 0 v * conjugate q)^._ijk
+rotate q v = ijk where
+  Quaternion _ ijk = q * Quaternion 0 v * conjugate q
 {-# SPECIALIZE rotate :: Quaternion Float -> V3 Float -> V3 Float #-}
 {-# SPECIALIZE rotate :: Quaternion Double -> V3 Double -> V3 Double #-}
 
@@ -398,6 +412,6 @@
 -- | @'axisAngle' axis theta@ builds a 'Quaternion' representing a
 -- rotation of @theta@ radians about @axis@.
 axisAngle :: (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
-axisAngle axis theta = normalize $ Quaternion (cos half) $ (sin half) *^ axis
+axisAngle axis theta = normalize $ Quaternion (cos half) $ sin half *^ axis
   where half = theta / 2
 {-# INLINE axisAngle #-}
diff --git a/src/Linear/V2.hs b/src/Linear/V2.hs
--- a/src/Linear/V2.hs
+++ b/src/Linear/V2.hs
@@ -21,18 +21,36 @@
   ) where
 
 import Control.Applicative
-import Control.Lens
 import Data.Data
 import Data.Distributive
 import Data.Foldable
+import Data.Traversable
 import Data.Monoid
 import Foreign.Ptr (castPtr)
 import Foreign.Storable (Storable(..))
 import GHC.Arr (Ix(..))
+import Linear.Core
 import Linear.Metric
 import Linear.Epsilon
+import Prelude hiding (sum)
 
+-- $setup
+-- >>> import Control.Lens
+
 -- | A 2-dimensional vector
+--
+-- >>> pure 1 :: V2 Int
+-- V2 1 1
+--
+-- >>> V2 1 2 + V2 3 4
+-- V2 4 6
+--
+-- >>> V2 1 2 * V2 3 4
+-- V2 3 8
+--
+-- >>> sum (V2 1 2)
+-- 3
+
 data V2 a = V2 a a deriving (Eq,Ord,Show,Read,Data,Typeable)
 
 instance Functor V2 where
@@ -58,7 +76,9 @@
 instance Monad V2 where
   return a = V2 a a
   {-# INLINE return #-}
-  (>>=) = bindRep
+  V2 a b >>= f = V2 a' b' where
+    V2 a' _ = f a
+    V2 _ b' = f b
   {-# INLINE (>>=) #-}
 
 instance Num a => Num (V2 a) where
@@ -91,10 +111,23 @@
 
 -- | A space that distinguishes 2 orthogonal basis vectors '_x' and '_y', but may have more.
 class R2 t where
+  -- |
+  -- >>> V2 1 2 ^._x
+  -- 1
+  --
+  -- >>> V2 1 2 & _x .~ 3
+  -- V2 3 2
   _x :: Functor f => (a -> f a) -> t a -> f (t a)
   _x = _xy._x
   {-# INLINE _x #-}
 
+  -- |
+  -- >>> V2 1 2 ^._y
+  -- 2
+  --
+  -- >>> V2 1 2 & _y .~ 3
+  -- V2 1 3
+
   _y :: Functor f => (a -> f a) -> t a -> f (t a)
   _y = _xy._y
   {-# INLINE _y #-}
@@ -104,20 +137,23 @@
 instance R2 V2 where
   _x f (V2 a b) = (`V2` b) <$> f a
   {-# INLINE _x #-}
-  _y f (V2 a b) = (V2 a) <$> f b
+  _y f (V2 a b) = V2 a <$> f b
   {-# INLINE _y #-}
   _xy = id
   {-# INLINE _xy #-}
 
-instance Representable V2 where
-  rep f = V2 (f _x) (f _y)
-  {-# INLINE rep #-}
+instance Core V2 where
+  core f = V2 (f _x) (f _y)
+  {-# INLINE core #-}
 
 instance Distributive V2 where
-  distribute f = V2 (fmap (^._x) f) (fmap (^._y) f)
+  distribute f = V2 (fmap (\(V2 x _) -> x) f) (fmap (\(V2 _ y) -> y) f)
   {-# INLINE distribute #-}
 
 -- | the counter-clockwise perpendicular vector
+--
+-- >>> perp $ V2 10 20
+-- V2 (-20) 10
 perp :: Num a => V2 a -> V2 a
 perp (V2 a b) = V2 (negate b) a
 {-# INLINE perp #-}
@@ -126,7 +162,7 @@
   nearZero = nearZero . quadrance
   {-# INLINE nearZero #-}
 
-instance forall a. Storable a => Storable (V2 a) where
+instance Storable a => Storable (V2 a) where
   sizeOf _ = 2 * sizeOf (undefined::a)
   {-# INLINE sizeOf #-}
   alignment _ = alignment (undefined::a)
diff --git a/src/Linear/V3.hs b/src/Linear/V3.hs
--- a/src/Linear/V3.hs
+++ b/src/Linear/V3.hs
@@ -19,14 +19,15 @@
   ) where
 
 import Control.Applicative
-import Control.Lens
 import Data.Data
 import Data.Distributive
 import Data.Foldable
+import Data.Traversable
 import Data.Monoid
 import Foreign.Ptr (castPtr)
 import Foreign.Storable (Storable(..))
 import GHC.Arr (Ix(..))
+import Linear.Core
 import Linear.Epsilon
 import Linear.Metric
 import Linear.V2
@@ -57,7 +58,10 @@
 instance Monad V3 where
   return a = V3 a a a
   {-# INLINE return #-}
-  (>>=) = bindRep
+  V3 a b c >>= f = V3 a' b' c' where
+    V3 a' _ _ = f a
+    V3 _ b' _ = f b
+    V3 _ _ c' = f c
   {-# INLINE (>>=) #-}
 
 instance Num a => Num (V3 a) where
@@ -89,7 +93,7 @@
   {-# INLINABLE dot #-}
 
 instance Distributive V3 where
-  distribute f = V3 (fmap (^._x) f) (fmap (^._y) f) (fmap (^._z) f)
+  distribute f = V3 (fmap (\(V3 x _ _) -> x) f) (fmap (\(V3 _ y _) -> y) f) (fmap (\(V3 _ _ z) -> z) f)
   {-# INLINE distribute #-}
 
 -- | A space that distinguishes 3 orthogonal basis vectors: '_x', '_y', and '_z'. (It may have more)
@@ -111,11 +115,11 @@
   _xyz = id
   {-# INLINE _xyz #-}
 
-instance Representable V3 where
-  rep f = V3 (f _x) (f _y) (f _z)
-  {-# INLINE rep #-}
+instance Core V3 where
+  core f = V3 (f _x) (f _y) (f _z)
+  {-# INLINE core #-}
 
-instance forall a. Storable a => Storable (V3 a) where
+instance Storable a => Storable (V3 a) where
   sizeOf _ = 3 * sizeOf (undefined::a)
   {-# INLINE sizeOf #-}
   alignment _ = alignment (undefined::a)
@@ -155,8 +159,8 @@
 
   unsafeIndex (V3 l1 l2 l3,V3 u1 u2 u3) (V3 i1 i2 i3) =
     unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-    unsafeIndex (l1,u1) i1))
+    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) *
+    unsafeIndex (l1,u1) i1)
   {-# INLINE unsafeIndex #-}
 
   inRange (V3 l1 l2 l3,V3 u1 u2 u3) (V3 i1 i2 i3) =
diff --git a/src/Linear/V4.hs b/src/Linear/V4.hs
--- a/src/Linear/V4.hs
+++ b/src/Linear/V4.hs
@@ -20,14 +20,15 @@
   ) where
 
 import Control.Applicative
-import Control.Lens
 import Data.Data
 import Data.Distributive
 import Data.Foldable
 import Data.Monoid
+import Data.Traversable
 import Foreign.Ptr (castPtr)
 import Foreign.Storable (Storable(..))
 import GHC.Arr (Ix(..))
+import Linear.Core
 import Linear.Epsilon
 import Linear.Metric
 import Linear.V2
@@ -59,7 +60,11 @@
 instance Monad V4 where
   return a = V4 a a a a
   {-# INLINE return #-}
-  (>>=) = bindRep
+  V4 a b c d >>= f = V4 a' b' c' d' where
+    V4 a' _ _ _ = f a
+    V4 _ b' _ _ = f b
+    V4 _ _ c' _ = f c
+    V4 _ _ _ d' = f d
   {-# INLINE (>>=) #-}
 
 instance Num a => Num (V4 a) where
@@ -91,7 +96,10 @@
   {-# INLINE dot #-}
 
 instance Distributive V4 where
-  distribute f = V4 (fmap (^._x) f) (fmap (^._y) f) (fmap (^._z) f) (fmap (^._w) f)
+  distribute f = V4 (fmap (\(V4 x _ _ _) -> x) f)
+                    (fmap (\(V4 _ y _ _) -> y) f)
+                    (fmap (\(V4 _ _ z _) -> z) f)
+                    (fmap (\(V4 _ _ _ w) -> w) f)
   {-# INLINE distribute #-}
 
 -- | A space that distinguishes orthogonal basis vectors '_x', '_y', '_z', '_w'. (It may have more.)
@@ -119,11 +127,11 @@
   _xyzw = id
   {-# INLINE _xyzw #-}
 
-instance Representable V4 where
-  rep f = V4 (f _x) (f _y) (f _z) (f _w)
-  {-# INLINE rep #-}
+instance Core V4 where
+  core f = V4 (f _x) (f _y) (f _z) (f _w)
+  {-# INLINE core #-}
 
-instance forall a. Storable a => Storable (V4 a) where
+instance Storable a => Storable (V4 a) where
   sizeOf _ = 4 * sizeOf (undefined::a)
   {-# INLINE sizeOf #-}
   alignment _ = alignment (undefined::a)
@@ -167,8 +175,8 @@
   unsafeIndex (V4 l1 l2 l3 l4,V4 u1 u2 u3 u4) (V4 i1 i2 i3 i4) =
     unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
     unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
-    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
-    unsafeIndex (l1,u1) i1)))
+    unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) *
+    unsafeIndex (l1,u1) i1))
   {-# INLINE unsafeIndex #-}
 
   inRange (V4 l1 l2 l3 l4,V4 u1 u2 u3 u4) (V4 i1 i2 i3 i4) =
diff --git a/src/Linear/Vector.hs b/src/Linear/Vector.hs
--- a/src/Linear/Vector.hs
+++ b/src/Linear/Vector.hs
@@ -17,37 +17,55 @@
   , (*^)
   , (^/)
   , lerp
-  , basis
-  , basisFor
+  -- , basis
+  -- , basisFor
   ) where
 
 import Control.Applicative
-import Control.Lens
 
+-- $setup
+-- >>> import Control.Lens
+-- >>> import Linear.V2
+
 infixl 6 ^+^, ^-^
 infixl 7 ^*, *^, ^/
 
 -- | Compute the sum of two vectors
+--
+-- >>> V2 1 2 ^+^ V2 3 4
+-- V2 4 6
 (^+^) :: (Applicative f, Num a) => f a -> f a -> f a
 (^+^) = liftA2 (+)
 {-# INLINE (^+^) #-}
 
 -- | Compute the negation of a vector
+--
+-- >>> gnegate (V2 2 4)
+-- V2 (-2) (-4)
 gnegate :: (Functor f, Num a) => f a -> f a
 gnegate = fmap negate
 {-# INLINE gnegate #-}
 
 -- | Compute the difference between two vectors
+--
+-- >>> V2 4 5 - V2 3 1
+-- V2 1 4
 (^-^) :: (Applicative f, Num a) => f a -> f a -> f a
 (^-^) = liftA2 (-)
 {-# INLINE (^-^) #-}
 
 -- | Compute the left scalar product
+--
+-- >>> 2 *^ V2 3 4
+-- V2 6 8
 (*^) :: (Functor f, Num a) => a -> f a -> f a
 (*^) a = fmap (a*)
 {-# INLINE (*^) #-}
 
 -- | Compute the right scalar product
+--
+-- >>> V2 3 4 ^* 2
+-- V2 6 8
 (^*) :: (Functor f, Num a) => f a -> a -> f a
 f ^* a = fmap (*a) f
 {-# INLINE (^*) #-}
@@ -62,6 +80,8 @@
 lerp alpha u v = alpha *^ u ^+^ (1 - alpha) *^ v
 {-# INLINE lerp #-}
 
+{-
+
 -- | Produce a default basis for a vector space. If the dimensionality
 -- of the vector space is not statically known, see 'basisFor'.
 basis :: (Applicative t, Traversable t, Num a) => [t a]
@@ -75,3 +95,5 @@
   where z = 0 <$ v
         n = lengthOf folded z
         aux i = z & element i .~ 1
+
+-}
