diff --git a/Numeric/AD.hs b/Numeric/AD.hs
--- a/Numeric/AD.hs
+++ b/Numeric/AD.hs
@@ -100,7 +100,8 @@
 import Data.Traversable (Traversable)
 import Data.Foldable (Foldable, foldr')
 import Control.Applicative
-import Numeric.AD.Internal (AD(..), probed, unprobe, UU, UF, FU, FF)
+import Numeric.AD.Internal (AD(..), UU, UF, FU, FF)
+import Numeric.AD.Internal.Identity (probed, unprobe)
 import Numeric.AD.Internal.Classes  (Mode(..))
 import Numeric.AD.Forward  (diff, diff', diffF, diffF', du, du', duF, duF', diffM, diffM', jacobianT, jacobianWithT) 
 import Numeric.AD.Tower    (diffsF, diffs0F , diffs, diffs0, taylor, taylor0, maclaurin, maclaurin0, dus, dus0, dusF, dus0F)
diff --git a/Numeric/AD/Internal.hs b/Numeric/AD/Internal.hs
--- a/Numeric/AD/Internal.hs
+++ b/Numeric/AD/Internal.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE Rank2Types, GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
 -- {-# OPTIONS_HADDOCK hide, prune #-}
 -----------------------------------------------------------------------------
 -- |
@@ -12,168 +11,9 @@
 -----------------------------------------------------------------------------
 module Numeric.AD.Internal
     ( module Numeric.AD.Internal.Classes
-    , UU, UF, FU, FF
-    , zipWithT
-    , zipWithDefaultT
-    , on
-    , AD(..)
-    , Id(..)
-    , probe
-    , unprobe
-    , probed
-    , unprobed
-    , Pair(..)
+    , module Numeric.AD.Internal.Types
     ) where
 
-import Control.Applicative
-import Language.Haskell.TH
 import Numeric.AD.Internal.Classes
-import Data.Monoid
-import Data.Traversable (Traversable, mapAccumL)
-import Data.Foldable (Foldable, toList)
-
--- | A scalar-to-scalar automatically-differentiable function.
-type UU a = forall s. Mode s => AD s a -> AD s a
--- | A scalar-to-non-scalar automatically-differentiable function.
-type UF f a = forall s. Mode s => AD s a -> f (AD s a)
--- | A non-scalar-to-scalar automatically-differentiable function.
-type FU f a = forall s. Mode s => f (AD s a) -> AD s a
--- | A non-scalar-to-non-scalar automatically-differentiable function.
-type FF f g a = forall s. Mode s => f (AD s a) -> g (AD s a)
-
-on :: (a -> a -> b) -> (c -> a) -> c -> c -> b
-on f g a b = f (g a) (g b)
-
-data Pair a b = Pair a b deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable)
-
-zipWithT :: (Foldable f, Traversable g) => (a -> b -> c) -> f a -> g b -> g c
-zipWithT f as = snd . mapAccumL (\(a:as') b -> (as', f a b)) (toList as)
-
-zipWithDefaultT :: (Foldable f, Traversable g) => a -> (a -> b -> c) -> f a -> g b -> g c
-zipWithDefaultT z f as = zipWithT f (toList as ++ repeat z)
-
-class Iso a b where
-    iso :: f a -> f b
-    osi :: f b -> f a
-
-instance Iso a a where
-    iso = id
-    osi = id
-
--- | 'AD' serves as a common wrapper for different 'Mode' instances, exposing a traditional
--- numerical tower. Universal quantification is used to limit the actions in user code to
--- machinery that will return the same answers under all AD modes, allowing us to use modes
--- interchangeably as both the type level \"brand\" and dictionary, providing a common API.
-newtype AD f a = AD { runAD :: f a } deriving (Iso (f a), Lifted, Mode, Primal)
-
-
--- > instance (Lifted f, Num a) => Num (AD f a)
--- etc.
-let f = varT (mkName "f") in 
-    deriveNumeric 
-        (classP ''Lifted [f]:) 
-        (conT ''AD `appT` f)
-
-newtype Id a = Id a deriving
-    (Iso a, Eq, Ord, Show, Enum, Bounded, Num, Real, Fractional, Floating, RealFrac, RealFloat, Monoid)
-
-probe :: a -> AD Id a
-probe a = AD (Id a)
-
-unprobe :: AD Id a -> a
-unprobe (AD (Id a)) = a
-
-pid :: f a -> f (Id a)
-pid = iso
-
-unpid :: f (Id a) -> f a
-unpid = osi
-
-probed :: f a -> f (AD Id a)
-probed = iso . pid
-
-unprobed :: f (AD Id a) -> f a
-unprobed = unpid . osi
-
-instance Functor Id where
-    fmap f (Id a) = Id (f a)
-
-instance Applicative Id where
-    pure = Id
-    Id f <*> Id a = Id (f a)
-
-instance Monad Id where
-    return = Id
-    Id a >>= f = f a
-
-instance Lifted Id where
-    (==!) = (==)
-    compare1 = compare
-    showsPrec1 = showsPrec
-    fromInteger1 = fromInteger
-    (+!) = (+)
-    (-!) = (-)
-    (*!) = (*)
-    negate1 = negate
-    abs1 = abs
-    signum1 = signum
-    (/!) = (/)
-    recip1 = recip
-    fromRational1 = fromRational
-    toRational1 = toRational
-    pi1 = pi
-    exp1 = exp
-    log1 = log
-    sqrt1 = sqrt
-    (**!) = (**)
-    logBase1 = logBase
-    sin1 = sin
-    cos1 = cos
-    tan1 = tan
-    asin1 = asin
-    acos1 = acos
-    atan1 = atan
-    sinh1 = sinh
-    cosh1 = cosh
-    tanh1 = tanh
-    asinh1 = asinh
-    acosh1 = acosh
-    atanh1 = atanh
-    properFraction1 = properFraction
-    truncate1 = truncate
-    round1 = round
-    ceiling1 = ceiling
-    floor1 = floor
-    floatRadix1 = floatRadix
-    floatDigits1 = floatDigits
-    floatRange1 = floatRange
-    decodeFloat1 = decodeFloat
-    encodeFloat1 = encodeFloat
-    exponent1 = exponent
-    significand1 = significand
-    scaleFloat1 = scaleFloat
-    isNaN1 = isNaN
-    isInfinite1 = isInfinite
-    isDenormalized1 = isDenormalized
-    isNegativeZero1 = isNegativeZero
-    isIEEE1 = isIEEE
-    atan21 = atan2
-    succ1 = succ
-    pred1 = pred
-    toEnum1 = toEnum
-    fromEnum1 = fromEnum
-    enumFrom1 = enumFrom
-    enumFromThen1 = enumFromThen
-    enumFromTo1 = enumFromTo
-    enumFromThenTo1 = enumFromThenTo
-    minBound1 = minBound
-    maxBound1 = maxBound
-
-instance Mode Id where
-    lift = Id
-    Id a ^* b = Id (a * b)
-    a *^ Id b = Id (a * b)
-    Id a <+> Id b = Id (a + b)
+import Numeric.AD.Internal.Types
 
-instance Primal Id where
-    primal (Id a) = a
diff --git a/Numeric/AD/Internal/Classes.hs b/Numeric/AD/Internal/Classes.hs
--- a/Numeric/AD/Internal/Classes.hs
+++ b/Numeric/AD/Internal/Classes.hs
@@ -22,6 +22,7 @@
     , deriveLifted
     , deriveNumeric
     , Lifted(..)
+    , Iso(..)
     ) where
 
 import Control.Applicative
@@ -32,6 +33,14 @@
 infixl 7 *!, /!, ^*, *^, ^/
 infixl 6 +!, -!, <+>
 infix 4 ==!
+
+class Iso a b where
+    iso :: f a -> f b
+    osi :: f b -> f a
+
+instance Iso a a where
+    iso = id
+    osi = id
 
 class Lifted t where
     showsPrec1          :: Show a => Int -> t a -> ShowS
diff --git a/Numeric/AD/Internal/Combinators.hs b/Numeric/AD/Internal/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/Numeric/AD/Internal/Combinators.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Numeric.AD.Internal.Combinators
+-- Copyright   :  (c) Edward Kmett 2010
+-- License     :  BSD3
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  GHC only
+--
+-----------------------------------------------------------------------------
+module Numeric.AD.Internal.Combinators
+    ( zipWithT
+    , zipWithDefaultT
+    , on
+    ) where
+
+import Data.Traversable (Traversable, mapAccumL)
+import Data.Foldable (Foldable, toList)
+
+on :: (a -> a -> b) -> (c -> a) -> c -> c -> b
+on f g a b = f (g a) (g b)
+
+zipWithT :: (Foldable f, Traversable g) => (a -> b -> c) -> f a -> g b -> g c
+zipWithT f as = snd . mapAccumL (\(a:as') b -> (as', f a b)) (toList as)
+
+zipWithDefaultT :: (Foldable f, Traversable g) => a -> (a -> b -> c) -> f a -> g b -> g c
+zipWithDefaultT z f as = zipWithT f (toList as ++ repeat z)
diff --git a/Numeric/AD/Internal/Forward.hs b/Numeric/AD/Internal/Forward.hs
--- a/Numeric/AD/Internal/Forward.hs
+++ b/Numeric/AD/Internal/Forward.hs
@@ -34,6 +34,7 @@
 import Data.Data
 import Control.Applicative
 import Numeric.AD.Internal
+import Numeric.AD.Internal.Identity
 
 data Forward a = Forward a a deriving (Show, Data, Typeable)
 
diff --git a/Numeric/AD/Internal/Identity.hs b/Numeric/AD/Internal/Identity.hs
new file mode 100644
--- /dev/null
+++ b/Numeric/AD/Internal/Identity.hs
@@ -0,0 +1,135 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Numeric.AD.Internal.Identity
+-- Copyright   :  (c) Edward Kmett 2010
+-- License     :  BSD3
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  GHC only
+--
+-----------------------------------------------------------------------------
+module Numeric.AD.Internal.Identity
+    ( Id(..)
+    , probe
+    , unprobe
+    , probed
+    , unprobed
+    ) where
+
+import Control.Applicative
+import Numeric.AD.Internal.Classes
+import Numeric.AD.Internal.Types
+import Data.Monoid
+import Data.Traversable (Traversable, traverse)
+import Data.Foldable (Foldable, foldMap)
+
+newtype Id a = Id a deriving
+    (Iso a, Eq, Ord, Show, Enum, Bounded, Num, Real, Fractional, Floating, RealFrac, RealFloat, Monoid)
+
+probe :: a -> AD Id a
+probe a = AD (Id a)
+
+unprobe :: AD Id a -> a
+unprobe (AD (Id a)) = a
+
+pid :: f a -> f (Id a)
+pid = iso
+
+unpid :: f (Id a) -> f a
+unpid = osi
+
+probed :: f a -> f (AD Id a)
+probed = iso . pid
+
+unprobed :: f (AD Id a) -> f a
+unprobed = unpid . osi
+
+instance Functor Id where
+    fmap f (Id a) = Id (f a)
+
+instance Foldable Id where
+    foldMap f (Id a) = f a
+
+instance Traversable Id where
+    traverse f (Id a) = Id <$> f a
+
+instance Applicative Id where
+    pure = Id
+    Id f <*> Id a = Id (f a)
+
+instance Monad Id where
+    return = Id
+    Id a >>= f = f a
+
+instance Lifted Id where
+    (==!) = (==)
+    compare1 = compare
+    showsPrec1 = showsPrec
+    fromInteger1 = fromInteger
+    (+!) = (+)
+    (-!) = (-)
+    (*!) = (*)
+    negate1 = negate
+    abs1 = abs
+    signum1 = signum
+    (/!) = (/)
+    recip1 = recip
+    fromRational1 = fromRational
+    toRational1 = toRational
+    pi1 = pi
+    exp1 = exp
+    log1 = log
+    sqrt1 = sqrt
+    (**!) = (**)
+    logBase1 = logBase
+    sin1 = sin
+    cos1 = cos
+    tan1 = tan
+    asin1 = asin
+    acos1 = acos
+    atan1 = atan
+    sinh1 = sinh
+    cosh1 = cosh
+    tanh1 = tanh
+    asinh1 = asinh
+    acosh1 = acosh
+    atanh1 = atanh
+    properFraction1 = properFraction
+    truncate1 = truncate
+    round1 = round
+    ceiling1 = ceiling
+    floor1 = floor
+    floatRadix1 = floatRadix
+    floatDigits1 = floatDigits
+    floatRange1 = floatRange
+    decodeFloat1 = decodeFloat
+    encodeFloat1 = encodeFloat
+    exponent1 = exponent
+    significand1 = significand
+    scaleFloat1 = scaleFloat
+    isNaN1 = isNaN
+    isInfinite1 = isInfinite
+    isDenormalized1 = isDenormalized
+    isNegativeZero1 = isNegativeZero
+    isIEEE1 = isIEEE
+    atan21 = atan2
+    succ1 = succ
+    pred1 = pred
+    toEnum1 = toEnum
+    fromEnum1 = fromEnum
+    enumFrom1 = enumFrom
+    enumFromThen1 = enumFromThen
+    enumFromTo1 = enumFromTo
+    enumFromThenTo1 = enumFromThenTo
+    minBound1 = minBound
+    maxBound1 = maxBound
+
+instance Mode Id where
+    lift = Id
+    Id a ^* b = Id (a * b)
+    a *^ Id b = Id (a * b)
+    Id a <+> Id b = Id (a + b)
+
+instance Primal Id where
+    primal (Id a) = a
diff --git a/Numeric/AD/Internal/Iterated.hs b/Numeric/AD/Internal/Iterated.hs
--- a/Numeric/AD/Internal/Iterated.hs
+++ b/Numeric/AD/Internal/Iterated.hs
@@ -25,6 +25,7 @@
 -- import Data.Typeable
 import Numeric.AD.Internal
 import Numeric.AD.Internal.Comonad
+import Numeric.AD.Internal.Combinators (on)
 import Language.Haskell.TH
 
 infixl 3 :|
diff --git a/Numeric/AD/Internal/Reverse.hs b/Numeric/AD/Internal/Reverse.hs
--- a/Numeric/AD/Internal/Reverse.hs
+++ b/Numeric/AD/Internal/Reverse.hs
@@ -49,6 +49,7 @@
 import System.IO.Unsafe (unsafePerformIO)
 import Language.Haskell.TH
 import Numeric.AD.Internal
+import Numeric.AD.Internal.Identity
 
 -- | A @Tape@ records the information needed back propagate from the output to each input during 'Reverse' 'Mode' AD.
 data Tape a t
diff --git a/Numeric/AD/Internal/Types.hs b/Numeric/AD/Internal/Types.hs
new file mode 100644
--- /dev/null
+++ b/Numeric/AD/Internal/Types.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE Rank2Types, GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
+-- {-# OPTIONS_HADDOCK hide, prune #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Numeric.AD.Internal.Types
+-- Copyright   :  (c) Edward Kmett 2010
+-- License     :  BSD3
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  GHC only
+--
+-----------------------------------------------------------------------------
+module Numeric.AD.Internal.Types
+    ( AD(..)
+    , UU, UF, FU, FF
+    ) where
+
+import Language.Haskell.TH
+import Numeric.AD.Internal.Classes
+
+-- | 'AD' serves as a common wrapper for different 'Mode' instances, exposing a traditional
+-- numerical tower. Universal quantification is used to limit the actions in user code to
+-- machinery that will return the same answers under all AD modes, allowing us to use modes
+-- interchangeably as both the type level \"brand\" and dictionary, providing a common API.
+newtype AD f a = AD { runAD :: f a } deriving (Iso (f a), Lifted, Mode, Primal)
+
+-- > instance (Lifted f, Num a) => Num (AD f a)
+-- etc.
+let f = varT (mkName "f") in 
+    deriveNumeric 
+        (classP ''Lifted [f]:) 
+        (conT ''AD `appT` f)
+
+-- | A scalar-to-scalar automatically-differentiable function.
+type UU a = forall s. Mode s => AD s a -> AD s a
+-- | A scalar-to-non-scalar automatically-differentiable function.
+type UF f a = forall s. Mode s => AD s a -> f (AD s a)
+-- | A non-scalar-to-scalar automatically-differentiable function.
+type FU f a = forall s. Mode s => f (AD s a) -> AD s a
+-- | A non-scalar-to-non-scalar automatically-differentiable function.
+type FF f g a = forall s. Mode s => f (AD s a) -> g (AD s a)
+
diff --git a/ad.cabal b/ad.cabal
--- a/ad.cabal
+++ b/ad.cabal
@@ -1,5 +1,5 @@
 Name:         ad
-Version:      0.28
+Version:      0.30.0
 License:      BSD3
 License-File: LICENSE
 Copyright:    (c) Edward Kmett 2010,
@@ -11,9 +11,13 @@
 Homepage:     http://comonad.com/reader/
 Synopsis:     Automatic Differentiation
 Description:  
-    Forward, reverse, and higher-order automatic differentiation combinators with a common API.
+    Forward-, reverse- and mixed- mode automatic differentiation combinators with a common API.
     . 
-    Type-level \"branding\" is used to prevent the end user from confusing infinitesimals.
+    Type-level \"branding\" is used to both prevent the end user from confusing infinitesimals 
+    and to limit unsafe access to the implementation details of each Mode.
+    .
+    The combinators in "Numeric.AD" choose from a variety of automatic differentiation modes,
+    based on the arity of their inputs and outputs.
 
 Build-Type:   Simple
 Build-Depends:       
@@ -35,6 +39,8 @@
 
     Numeric.AD.Internal
     Numeric.AD.Internal.Classes
+    Numeric.AD.Internal.Types
+    Numeric.AD.Internal.Combinators
     Numeric.AD.Internal.Comonad
     Numeric.AD.Internal.Stream
     Numeric.AD.Internal.Tensors
@@ -43,7 +49,8 @@
     Numeric.AD.Internal.Forward
     Numeric.AD.Internal.Reverse
     Numeric.AD.Internal.Tower
+    Numeric.AD.Internal.Identity
     Numeric.AD.Internal.Iterated
 
 Extra-Source-Files: TODO
-GHC-Options: -Wall
+GHC-Options: -Wall -fspec-constr -O2
