diff --git a/Data/Rope/Annotated.hs b/Data/Rope/Annotated.hs
--- a/Data/Rope/Annotated.hs
+++ b/Data/Rope/Annotated.hs
@@ -1,38 +1,159 @@
+{-# LANGUAGE TypeOperators, Rank2Types, EmptyDataDecls, 
+             MultiParamTypeClasses, FunctionalDependencies, 
+             FlexibleContexts, FlexibleInstances, UndecidableInstances,
+             TypeFamilies, IncoherentInstances, OverlappingInstances #-}
 module Data.Rope.Annotated
-    ( 
-    -- * Annotated 'Rope's 
+    ( -- * Annotated 'Rope's 
       A(rope)   
     , Ann
-    , Annotation
-    -- * Unpacking Annotated 'Rope'
+    , MonoidA, ReducerA, BreakableA 
+    , runAnn     -- :: Ann a f -> (forall b. Ann b f -> r) -> r
+
+      -- * Unpacking 'Ropes'
     , null      -- :: A s a -> Bool
     , head      -- :: Unpackable t => A s a -> t
     , last      -- :: Unpackable t => A s a -> t
-    , uncons    -- :: (Annotation f, Unpackable t, Uncons t a b) => Ann a f -> Maybe (t, Ann b f)
-    , unsnoc    -- :: (Annotation f, Unpackable t, Unsnoc t a b) => Ann a f -> Maybe (t, Ann b f)
+    , unpack    -- :: Unpackable t => A s a -> [t]
 
-    -- * Building Annotated 'Rope'
-    , empty     -- :: (Annotation f) => Ann Empty f 
-    , append    -- :: (Annotation f, Append a b c) => Ann a f -> Ann b f -> Ann c f
-    , unit      -- :: (Annotation f, Reducer t Rope) => t -> Ann a f
-    , snoc      -- :: (Annotation f, Reducer t Rope) => t -> Ann a f -> (forall c. Ann (Snoc c t a) f -> r) -> r
-    , cons      -- :: (Annotation f, Reducer t Rope) => Ann a f -> t -> (forall c. Ann (Cons c t a) f -> r) -> r
+      -- * Building Annotated 'Rope'
+    , empty     -- :: MonoidA f => Ann Empty f 
+    , append    -- :: MonoidA f => Ann a f -> Ann b f -> Ann (a :<> b) f
 
-    -- * Cutting An Annotated 'Rope'
-    , splitAt   -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-    , drop      -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
-    , take      -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-    , break     -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-    , span      -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-    , takeWhile -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-    , dropWhile -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
+    , unit      -- :: (ReducerA f, Reducer t Rope) => t -> (forall a. Ann (Unit a) f -> r) -> r
+    , snoc      -- :: (ReducerA f, Reducer t Rope) => t -> Ann a f -> (forall c. Ann (Snoc c t a) f -> r) -> r
+    , cons      -- :: (ReducerA f, Reducer t Rope) => Ann a f -> t -> (forall c. Ann (Cons c t a) f -> r) -> r
 
+      -- * Cutting An Annotated 'Rope'
+    , splitAt   -- :: (BreakablaA f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
+    , drop      -- :: (BreakableA f) => Int -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
+    , take      -- :: (BreakablaA f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
+
+    , break     -- :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
+    , span      -- :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
+    , takeWhile -- :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
+    , dropWhile -- :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
+
+    -- * Inspecting the ends of the 'Rope'
+    , uncons    -- :: (BreakableA f, Unpackable t) => Ann a f -> Maybe (t, Ann (Unit (Tail t b)) f)
+    , unsnoc    -- :: (BreakableA f, Unpackable t) => Ann a f -> Maybe (Ann (Unit (Init b t)) f, t)
+
     -- * Type-level constructors
-    , Drop, Take, Snoc, Cons, Tail, Init, Empty, (:<>)
+    , Drop, Take, Snoc, Cons, Tail, Init, Return, Nil , (:<>)
 
-    -- * Annotation Product
-    , (:*:)(..), fstF, sndF
+    -- * Annotations
+    -- ** Annotation Product
+    , (:*:)(..)
+    , fstF      -- :: (f :*: g) a -> f a 
+    , sndF      -- :: (f :*: g) a -> g a
+    -- ** Annotation Unit
+    , Unit
     ) where
 
 import Prelude hiding (null, head, last, take, drop, span, break, splitAt, takeWhile, dropWhile)
-import Data.Rope.Annotated.Internal
+import Data.Monoid
+
+import qualified Data.Rope.Internal as Rope
+
+import Data.Rope.Annotated.Internal (A(..), null, head, last, unpack)
+import Data.Rope.Annotation
+import Data.Rope.Annotation.Product
+import Data.Rope.Annotation.Unit
+
+import Data.Rope.Util.Reducer (Reducer)
+import qualified Data.Rope.Util.Reducer as Reducer
+
+import Data.Rope.Internal (Rope(..),Breakable, Unpackable)
+
+type Ann a f = A a (f a)
+
+data Nil
+data a :> b 
+
+type family a :<> b :: *
+type instance (a :> b) :<> c = a :> (b :<> c)
+type instance Nil :<> c = c 
+type Return a = a :> Nil
+
+data Taken n a
+type family Take n a :: *
+type instance Take n Nil = Nil
+type instance Take n (a :> b) = Return (Taken n (a :> b))
+
+data Dropped n a 
+type family Drop n a :: *
+type instance Drop n Nil = Nil
+type instance Drop n (a :> b) = Return (Dropped n (a :> b))
+
+data Token s t 
+type Cons s t a = Token s t :> a
+type Snoc a s t = a :<> Return (Token s t)
+
+data Tailed t a 
+type Tail t a = Unit (Tailed t a)
+
+data Inited a t
+type Init a t = Unit (Inited a t)
+
+runAnn :: Ann a f -> (forall b. Ann b f -> r) -> r
+runAnn a k = k a 
+
+empty :: MonoidA f => Ann Nil f
+empty = A Rope.empty emptyA
+
+append :: MonoidA f => Ann a f -> Ann b f -> Ann (a :<> b) f
+append (A r a) (A s b) = A (r `mappend` s) (appendA r a s b)
+
+unit :: (ReducerA f, Reducer t Rope) => t -> (forall a. Ann (Return a) f -> r) -> r
+unit t k = k (A r (unitA r)) 
+    where 
+        r :: Rope
+        r = Reducer.unit t
+
+splitAt :: BreakableA f => Int -> Ann a f -> (forall n. Ann (Take n a)  f -> Ann (Drop n a) f -> r) -> r
+splitAt n (A r a) k = k (A r b) (A r c) 
+    where (b, c) = splitAtA n r a
+
+drop :: BreakableA f => Int -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
+drop n (A r a) k = k (A r (dropA n r a))
+
+take :: BreakableA f => Int -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
+take n (A r a) k = k (A r (takeA n r a))
+
+snoc :: (ReducerA f, Reducer t Rope) => Ann a f -> t -> (forall c. Ann (Snoc a c t) f -> r) -> r
+snoc (A r a) t k = k (A r' (snocA (Rope.length r' - Rope.length r) r' a))
+    where r' = Reducer.snoc r t 
+
+cons :: (ReducerA f, Reducer t Rope) => t -> Ann a f -> (forall c. Ann (Cons c t a) f -> r) -> r
+cons t (A r a) k = k (A r' (consA (Rope.length r' - Rope.length r) r' a))
+    where r' = Reducer.cons t r
+
+break :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
+break p (A r a) k = k (A x b) (A y c) where
+    (x,y) = Rope.break p r
+    (b,c) = splitAtA (Rope.length x) r a
+
+span :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
+span p (A r a) k = k (A x b) (A y c) where
+    (x,y) = Rope.span p r
+    (b,c) = splitAtA (Rope.length x) r a
+
+takeWhile :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
+takeWhile p (A r a) k = k (A x b) where
+    x = Rope.takeWhile p r
+    b = takeA (Rope.length x) r a
+
+dropWhile :: (BreakableA f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
+dropWhile p (A r a) k = k (A y c) where
+    y = Rope.dropWhile p r
+    c = dropA (Rope.length r - Rope.length y) r a
+
+uncons :: (BreakableA f, Unpackable t) => Ann a f -> Maybe (t, Ann (Tail t a) f)
+uncons (A r a) = case Rope.uncons r of
+    Just (c,cs) -> Just (c, A cs (dropA (Rope.length r - Rope.length cs) r a))
+    Nothing -> Nothing
+
+unsnoc :: (BreakableA f, Unpackable t) => Ann a f -> Maybe (Ann (Init a t) f, t)
+unsnoc (A r a) = case Rope.unsnoc r of
+    Just (cs,c) -> Just (A cs (dropA (Rope.length cs) r a), c)
+    Nothing -> Nothing
+
diff --git a/Data/Rope/Annotated/Internal.hs b/Data/Rope/Annotated/Internal.hs
--- a/Data/Rope/Annotated/Internal.hs
+++ b/Data/Rope/Annotated/Internal.hs
@@ -4,59 +4,24 @@
              IncoherentInstances, OverlappingInstances #-}
 module Data.Rope.Annotated.Internal 
     ( A(A,rope)
-    , Ann
-    , Annotation(..)
-    , (:~>)
-
     , null      -- :: A s a -> Bool
     -- * Unpackable Ropes
     , head      -- :: Unpackable t => A s a -> t
     , last      -- :: Unpackable t => A s a -> t
     , unpack    -- :: Unpackable t => A s a -> [t]
-    , uncons    -- :: (Annotation f, Unpackable t) => Ann a f -> Maybe (t, Ann (Tail t a) f)
-    , unsnoc    -- :: (Annotation f, Unpackable t) => Ann a f -> Maybe (t, Ann (Init a t) f)
-
-    -- * Splitting Ropes
-    , drop      -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
-    , take      -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-    , splitAt   -- :: (Annotation f) => Int -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-
-    -- * Building Ropes
-    , unit      -- :: (Annotation f, Reducer t Rope) => t -> Ann a f
-    , snoc      -- :: (Annotation f, Reducer t Rope) => t -> Ann a f -> (forall c. Ann (Snoc c t a) f -> r) -> r
-    , cons      -- :: (Annotation f, Reducer t Rope) => Ann a f -> t -> (forall c. Ann (Cons c t a) f -> r) -> r
-    , empty     -- :: (Annotation f) => Ann Empty f 
-    , append    -- :: (Annotation f, ) => Ann a f -> Ann b f -> Ann (a :<> b) f
-
-    -- * Breaking Ropes
-
-    , break     -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-    , span      -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-    , takeWhile -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-    , dropWhile -- :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
-
-    -- * Type-level constructors
-    , Drop, Take, Snoc, Cons, Tail, Init, Empty, (:<>)
-
     -- * Annotation Products
-    , (:*:)(..), fstF, sndF
     ) where
 
 import Prelude hiding (null, head, last, take, drop, span, break, splitAt, takeWhile, dropWhile)
 import Control.Applicative hiding (empty)
 import Data.Rope.Util.Comonad
-import Data.Monoid
-import qualified Data.Rope.Util.Reducer as Reducer
-import Data.Rope.Util.Reducer (Reducer)
 import Data.FingerTree (Measured(..))
 import Data.Foldable (Foldable, foldMap)
 import qualified Data.Foldable
 import Data.Traversable (Traversable(traverse))
 import qualified Data.Rope.Internal as Rope
 import Data.Rope.Body (Offset(..))
-import Data.Rope.Internal (Rope(..),Breakable, Unpackable)
-
-type f :~> g = forall a. f a -> g a
+import Data.Rope.Internal (Rope(..),Unpackable)
 
 data A s a = A { rope :: !Rope, extractA :: a }
 
@@ -69,7 +34,8 @@
 last :: Unpackable t => A s a -> t
 last = Rope.last . rope
 
-type Ann a f = A a (f a)
+unpack :: Unpackable t => A s a -> [t]
+unpack (A s _) = Rope.unpack s
 
 instance Measured Offset (A s a) where
     measure = measure . rope
@@ -91,147 +57,3 @@
 
 instance Traversable (A s) where
     traverse f (A s a) = A s <$> f a
-
-class Annotation f where
-    unitA    :: Rope -> f a
-    splitAtA :: Int -> Rope -> f a -> (f b, f c)
-    takeA    :: Int -> Rope -> f a -> f b
-    dropA    :: Int -> Rope -> f a -> f b
-    snocA    :: Rope -> Int -> f a -> f b
-    consA    :: Int -> Rope -> f a -> f b
-    emptyA   :: f Empty
-    appendA  :: Ann a f -> Ann b f -> f (a :<> b)
-
-    takeA n r = fst . splitAtA n r
-    dropA n r = snd . splitAtA n r
-
-empty :: Annotation f => Ann Empty f
-empty = A Rope.empty emptyA
-
-
-unit :: (Reducer t Rope, Annotation f) => t -> Ann a f
-unit t = A r (unitA r)
-    where 
-        r :: Rope
-        r = Reducer.unit t
-
-splitAt :: Annotation f => Int -> Ann a f -> (forall n. Ann (Take n a)  f -> Ann (Drop n a) f -> r) -> r
-splitAt n (A r a) k = k (A r b) (A r c) 
-    where (b, c) = splitAtA n r a
-
-drop :: Annotation f => Int -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
-drop n (A r a) k = k (A r (dropA n r a))
-
-take :: Annotation f => Int -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-take n (A r a) k = k (A r (takeA n r a))
-
-snoc :: (Annotation f, Reducer t Rope) => Ann a f -> t -> (forall c. Ann (Snoc c t a) f -> r) -> r
-snoc (A r a) t k = k (A r' (snocA r' (Rope.length r' - Rope.length r) a))
-    where r' = Reducer.snoc r t 
-
-cons :: (Annotation f, Reducer t Rope) => t -> Ann a f -> (forall c. Ann (Cons c t a) f -> r) -> r
-cons t (A r a) k = k (A r' (consA (Rope.length r' - Rope.length r) r' a))
-    where r' = Reducer.cons t r
-
-append :: Annotation f => Ann a f -> Ann b f -> Ann (a :<> b) f
-append a@(A r _) b@(A s _) = A (r `mappend` s) (a `appendA` b)
-
-break     :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-break p (A r a) k = k (A x b) (A y c) where
-    (x,y) = Rope.break p r
-    (b,c) = splitAtA (Rope.length x) r a
-
-span      :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> Ann (Drop n a) f -> r) -> r
-span p (A r a) k = k (A x b) (A y c) where
-    (x,y) = Rope.span p r
-    (b,c) = splitAtA (Rope.length x) r a
-
-takeWhile :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Take n a) f -> r) -> r
-takeWhile p (A r a) k = k (A x b) where
-    x = Rope.takeWhile p r
-    b = takeA (Rope.length x) r a
-
-dropWhile :: (Annotation f, Breakable t) => (t -> Bool) -> Ann a f -> (forall n. Ann (Drop n a) f -> r) -> r
-dropWhile p (A r a) k = k (A y c) where
-    y = Rope.dropWhile p r
-    c = dropA (Rope.length r - Rope.length y) r a
-
-uncons :: (Annotation f, Unpackable t) => Ann a f -> Maybe (t, Ann (Tail t a) f)
-uncons (A r a) = case Rope.uncons r of
-    Just (c,cs) -> Just (c, A cs (dropA (Rope.length r - Rope.length cs) r a))
-    Nothing -> Nothing
-
-unsnoc :: (Annotation f, Unpackable t) => Ann a f -> Maybe (Ann (Init a t) f, t)
-unsnoc (A r a) = case Rope.unsnoc r of
-    Just (cs,c) -> Just (A cs (dropA (Rope.length cs) r a), c)
-    Nothing -> Nothing
-
--- annotation product
-
-infixr 5 :*:
-
-data (f :*: g) a = f a :*: g a
-
-fstF :: (f :*: g) :~> f
-fstF ~(f :*: _) = f
-
-sndF :: (f :*: g) :~> g
-sndF ~(_ :*: g) = g
-
-instance (Functor f, Functor g)  => Functor (f :*: g) where
-    fmap f (a :*: b) = fmap f a :*: fmap f b
-
-instance (Applicative f, Applicative g) => Applicative (f :*: g) where
-    pure a = pure a :*: pure a
-    (f :*: g) <*> (a :*: b) = (f <*> a) :*: (g <*> b)
-
-instance (Foldable f, Foldable g) => Foldable (f :*: g) where
-    foldMap f (a :*: b) = foldMap f a `mappend` foldMap f b
-    
-instance (Traversable f, Traversable g) => Traversable (f :*: g) where
-    traverse f (a :*: b) = (:*:) <$> traverse f a <*> traverse f b
-
-instance (Annotation f, Annotation g) => Annotation (f :*: g) where
-    unitA r = unitA r :*: unitA r
-    emptyA = emptyA :*: emptyA
-    dropA n r (f :*: g) = dropA n r f :*: dropA n r g
-    takeA n r (f :*: g) = takeA n r f :*: takeA n r g
-    splitAtA n r (f :*: g) = (f' :*: g' , f'' :*: g'') where
-        (f',f'') = splitAtA n r f
-        (g',g'') = splitAtA n r g
-    snocA r n (f :*: g) = snocA r n f :*: snocA r n g
-    consA n r (f :*: g) = consA n r f :*: consA n r g
-    appendA (A r (a :*: a')) (A s (b :*: b')) = 
-        appendA (A r a) (A s b) :*: appendA (A r a') (A s b')
-
-    
-data Take n a
-data Drop n a
-data Empty
-data Cons s t a
-data Snoc a s t
-data (:<>) a b
-data Tail t a
-data Init a t
-
-{-
-class Append a b c | a b -> c
-instance Append Empty a a
-instance Append b c d => Append (a :<> b) c (a :<> d)
-instance Append a b c => Append (Cons s t a) b (Cons s t c)
-instance Append (Take n a) (Drop n a) a
-instance Append a Empty a 
-instance Append a b (a :<> b)
-
-class Uncons t a b | t a -> b
-instance Uncons t (Cons s t a) a
-instance Uncons t a (Tail t a)
-
-class Unsnoc a t b | a t -> b
-instance Unsnoc (Snoc a s t) t a
-instance Unsnoc a t (Init a t)
--}
-
-unpack :: Unpackable t => A s a -> [t]
-unpack (A s _) = Rope.unpack s
-
diff --git a/Data/Rope/Annotation.hs b/Data/Rope/Annotation.hs
new file mode 100644
--- /dev/null
+++ b/Data/Rope/Annotation.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE TypeOperators #-}
+module Data.Rope.Annotation
+    ( MonoidA(..)
+    , ReducerA(..)
+    , BreakableA(..)
+    ) where
+
+import Data.Rope (Rope)
+
+class MonoidA f where
+    -- | build an empty 'Annotation'
+    emptyA   :: f a
+    -- | append two annotations
+    appendA  :: Rope -> f a -> Rope -> f b -> f c
+
+class MonoidA f => ReducerA f where
+    -- | construct an 'Annotation' from a 'Rope' out of whole cloth
+    unitA    :: Rope -> f a
+    -- | The 'Rope' has been updated to contains n more bytes on the right than the one used to build the 'Annotation', update the 'Annotation'
+    snocA    :: Int -> Rope -> f a -> f b
+    -- | The 'Rope' contains n more bytes on the left than the one used to build the 'Annotation', update the 'Annotation'
+    consA    :: Int -> Rope -> f a -> f b
+    
+class BreakableA f where
+
+    -- | split an 'Annotation' about a 'Rope' into two annotations, one about the first n bytes, the other about the remainder
+    splitAtA :: Int -> Rope -> f a -> (f b, f c)
+    -- | truncate the 'Annotation' to 'length' n
+    takeA    :: Int -> Rope -> f a -> f b
+    -- | drop the first n bytes from the 'Annotation'
+    dropA    :: Int -> Rope -> f a -> f b
+
+
+    takeA n r = fst . splitAtA n r
+    dropA n r = snd . splitAtA n r
diff --git a/Data/Rope/Annotation/Product.hs b/Data/Rope/Annotation/Product.hs
new file mode 100644
--- /dev/null
+++ b/Data/Rope/Annotation/Product.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE TypeOperators #-}
+module Data.Rope.Annotation.Product
+    ( (:*:)(..)
+    , fstF
+    , sndF
+    ) where
+
+import Control.Applicative hiding (empty)
+
+import Data.Monoid (mappend)
+import Data.Foldable (Foldable, foldMap)
+import qualified Data.Foldable
+import Data.Traversable (Traversable(traverse))
+
+import Data.Rope.Annotation
+
+infixr 5 :*:
+
+-- | A 'Rope' 'Annotation' product.
+data (f :*: g) a = f a :*: g a
+
+fstF :: (f :*: g) a -> f a 
+fstF ~(f :*: _) = f
+
+sndF :: (f :*: g) a -> g a
+sndF ~(_ :*: g) = g
+
+instance (Functor f, Functor g)  => Functor (f :*: g) where
+    fmap f (a :*: b) = fmap f a :*: fmap f b
+
+instance (Applicative f, Applicative g) => Applicative (f :*: g) where
+    pure a = pure a :*: pure a
+    (f :*: g) <*> (a :*: b) = (f <*> a) :*: (g <*> b)
+
+instance (Foldable f, Foldable g) => Foldable (f :*: g) where
+    foldMap f (a :*: b) = foldMap f a `mappend` foldMap f b
+    
+instance (Traversable f, Traversable g) => Traversable (f :*: g) where
+    traverse f (a :*: b) = (:*:) <$> traverse f a <*> traverse f b
+
+instance (MonoidA f, MonoidA g) => MonoidA (f :*: g) where
+    emptyA = emptyA :*: emptyA
+    appendA r (a :*: a') s (b :*: b') = 
+        appendA r a s b :*: appendA r a' s b'
+
+instance (ReducerA f, ReducerA g) => ReducerA (f :*: g) where
+    unitA r = unitA r :*: unitA r
+    snocA r n (f :*: g) = snocA r n f :*: snocA r n g
+    consA n r (f :*: g) = consA n r f :*: consA n r g
+
+instance (BreakableA f, BreakableA g) => BreakableA (f :*: g) where
+    dropA n r (f :*: g) = dropA n r f :*: dropA n r g
+    takeA n r (f :*: g) = takeA n r f :*: takeA n r g
+    splitAtA n r (f :*: g) = (f' :*: g' , f'' :*: g'') where
+        (f',f'') = splitAtA n r f
+        (g',g'') = splitAtA n r g
diff --git a/Data/Rope/Annotation/Unit.hs b/Data/Rope/Annotation/Unit.hs
new file mode 100644
--- /dev/null
+++ b/Data/Rope/Annotation/Unit.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE TypeOperators, EmptyDataDecls #-}
+module Data.Rope.Annotation.Unit
+    ( Unit
+    ) where
+
+import Data.Rope.Annotation
+
+data Unit a
+
+instance MonoidA Unit where
+    emptyA = undefined
+    appendA _ _ _ _ = undefined
+
+instance ReducerA Unit where
+    unitA _ = undefined
+    snocA _ _ _ = undefined
+    consA _ _ _ = undefined
+
+instance BreakableA Unit where
+    takeA _ _ _ = undefined
+    dropA _ _ _ = undefined
+    splitAtA _ _ _ = (undefined, undefined)
diff --git a/rope.cabal b/rope.cabal
--- a/rope.cabal
+++ b/rope.cabal
@@ -1,5 +1,5 @@
 name:           rope
-version:        0.3
+version:        0.4
 license:        BSD3
 license-file:   LICENSE
 author:         Edward A. Kmett
@@ -24,6 +24,9 @@
     Data.Rope
     Data.Rope.Annotated
     Data.Rope.Annotated.Internal
+    Data.Rope.Annotation
+    Data.Rope.Annotation.Product
+    Data.Rope.Annotation.Unit
     Data.Rope.Body
     Data.Rope.Internal
     Data.Rope.Util.Comonad
