diff --git a/renderable.cabal b/renderable.cabal
--- a/renderable.cabal
+++ b/renderable.cabal
@@ -10,20 +10,24 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.1.0.0
+version:             0.2.0.0
 
 -- A short (one-line) description of the package.
-synopsis:            Provides a nice API for rendering data types that change
-                     over time.
+synopsis:            An API for managing renderable resources.
 
 -- A longer description of the package.
-description: Instances of Renderable conform to a simple API that makes their
-             visual representations composable through hashing and cacheing.
-             Also provided are some convenience functions for writing
-             Renderable instances. Not provided are actual rendering functions.
+description: The `renderable` package provides a method for managing resources
+    of a rendering system. Resources are allocated according to a strategy and
+    released automatically when your renderable data changes. These changes are
+    detected during each draw call based on the hash of your renderable
+    datatype.
 
+    This package is meant to be pulled in as a portion of your rendering system.
+    It aims to ease the task of managing allocation of resources over time as
+    the value of your renderable datatype changes.
+
 -- URL for the project homepage or repository.
-homepage:            http://zyghost.com
+homepage:            https://github.com/schell/renderable
 
 -- The license under which the package is released.
 license:             MIT
@@ -36,7 +40,7 @@
 
 -- An email address to which users can send suggestions, bug reports, and
 -- patches.
-maintainer:          efsubenovex@gmail.com
+maintainer:          schell.scivally@synapsegroup.com
 
 -- A copyright notice.
 -- copyright:
@@ -65,12 +69,13 @@
   -- other-modules:
 
   -- LANGUAGE extensions used by modules in this package.
-  other-extensions:    TypeFamilies, GADTs, FlexibleContexts
+  other-extensions:
 
   -- Other library packages from which modules are imported.
   build-depends:       base >=4.8 && <4.9,
                        containers >= 0.5 && < 0.6,
-                       hashable >= 1.2 && < 1.3
+                       hashable >= 1.2 && < 1.3,
+                       transformers >= 0.4 && < 0.5
 
   -- Directories containing source files.
   hs-source-dirs:      src
diff --git a/src/Data/Renderable.hs b/src/Data/Renderable.hs
--- a/src/Data/Renderable.hs
+++ b/src/Data/Renderable.hs
@@ -1,164 +1,179 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
 module Data.Renderable (
-    Primitive(..),
-    Element(..),
-    Composite(..),
+    RenderStrategy(..),
+    Renderer,
     Rendering,
+    CleanOp,
     Cache,
-    renderData
+    CacheStats(..),
+    renderPrims,
+    renderPrimsDebug,
+    renderPrimsWithStats,
+    emptyRenderer,
+    appendRenderer
 ) where
 
 import Prelude hiding (lookup)
-import Control.Arrow (first)
 import Control.Monad
+import Control.Monad.IO.Class
 import Data.Hashable
 import Data.IntMap (IntMap)
 import qualified Data.IntMap as IM
 --------------------------------------------------------------------------------
--- Primitives
---------------------------------------------------------------------------------
--- | A 'Primitive' is the smallest thing can can be rendered in your graphics
--- system. Some examples are points, lines, triangles and other shapes.
-class Primitive a where
-    -- | The monad in which rendering calls will take place.
-    type PrimM a :: * -> *
-    -- | The type of the graphics transformation.
-    type PrimT a :: *
-    -- | The datatype that holds cached resources such as references to
-    -- windows, shaders, etc.
-    type PrimR a :: *
-    -- | Allocate resources for rendering the primitive and return
-    -- a monadic call that renders the primitive using a transform. Tuple
-    -- that with a call to clean up the allocated resources.
-    compilePrimitive :: Monad (PrimM a)
-                     => PrimR a
-                     -> a
-                     -> (PrimM a) (Rendering (PrimM a) (PrimT a))
---------------------------------------------------------------------------------
--- Element
+-- A strategy for rendering
 --------------------------------------------------------------------------------
--- | Element is an existential type that can be used to enclose
--- instances of Primitive in order to contain them all in a heterogeneous list.
--- 'm', 'r' and 't' must be shared with all Primitive instances stored in
--- the heterogeneous list of Elements.
-data Element m r t where
-    Element  :: ( Monad m, Hashable a, Primitive a
-                , m ~ PrimM a
-                , r ~ PrimR a
-                , t ~ PrimT a)
-             => a -> Element m r t
-
-instance Hashable (Element m r t) where
-    hashWithSalt s (Element a) = s `hashWithSalt` "Element" `hashWithSalt` a
+-- | A 'RenderStrategy' is a method for creating a renderer that can render
+-- your primitives. Examples of primitives are are points, lines, triangles and
+-- other shapes. A 'RenderStrategy' is parameterized by four types -
+--
+-- @m@ - the monad in which rendering calls will take place.
+--
+-- @t@ - type of the graphics transformation that can be applied to the
+--       renderer
+--
+-- @r@ - type that holds static resources such as windows, shaders, etc.
+--
+-- @a@ - type of the primitive that can be renderered.
+data RenderStrategy m t r a = RenderStrategy
+    { canAllocPrimitive :: r -> a -> Bool
+      -- ^ Determines whether a renderer can be allocated for the primitive.
+      -- A result of 'False' will defer compilation until a later time (the next
+      -- frame).
 
-instance Eq (Element m r t) where
-    a == b = hash a == hash b
---------------------------------------------------------------------------------
--- Compositing
---------------------------------------------------------------------------------
--- | A 'Composite' is a type that can be broken down into a list of
--- transformed primitives.
-class Composite a m r t where
-    -- | Break down a 'Composite' into a heterogeneous list of transformed
-    -- primitives.
-    composite :: a -> [(t, Element m r t)]
+    , compilePrimitive :: r -> a -> m (Renderer m t)
+      -- ^ Allocates resources for rendering the primitive and return
+      -- a monadic call that renders the primitive using a transform.
+      -- Tuples that with a call to clean up the allocated resources.
+    }
 --------------------------------------------------------------------------------
 -- Rendering
 --------------------------------------------------------------------------------
--- | A rendering is a type that contains some effectful computation for
--- displaying something given a transform. It also contains an effectful
--- computation for cleaning up any resources allocated during its creation.
-type Rendering m t = (m (), t -> m ())
+-- | A Rendering is an effectful computation for displaying something given a
+-- transform.
+type Rendering m t = t -> m ()
 
--- | A cache of renderings.
-type Cache m t = IntMap (Rendering m t)
+-- | A CleanOp is an effectfull computaton that cleans up any resources
+-- allocated during the creation of an associated Rendering.
+type CleanOp m = m ()
 
-instance Monad m => Monoid (Rendering m t) where
-    (ca, fa) `mappend` (cb, fb) = (ca >> cb, \t -> fa t >> fb t)
-    mempty = (return (), const $ return ())
+-- | A Renderer is the pairing of a Rendering and a Cleanup.
+type Renderer m t = (CleanOp m, Rendering m t)
 
-findRenderer :: Monad m
-             => Cache m t
-             -> (Cache m t, IntMap (Element m r t))
-             -> Element m r t
-             -> (Cache m t, IntMap (Element m r t))
+-- | Create a renderer that renders nothing and releases no resources.
+emptyRenderer :: Monad m => Renderer m t
+emptyRenderer = (return (), const $ return ())
+
+-- | Appends two renderers into one.
+appendRenderer :: Monad m => Renderer m t -> Renderer m t -> Renderer m t
+appendRenderer (c1,r1) (c2,r2) = (c1 >> c2, \t -> r1 t >> r2 t)
+
+-- | A cache of renderers.
+type Cache m t = IntMap (Renderer m t)
+
+findRenderer :: (Monad m, Hashable a)
+             => Cache m t -> (Cache m t, IntMap a) -> a -> (Cache m t, IntMap a)
 findRenderer cache (found, missing) a =
     let k = hash a in
     case IM.lookup k cache of
         Nothing -> (found, IM.insert k a missing)
         Just r  -> (IM.insert k r found, missing)
 
-getRenderer :: (Primitive a, Hashable a, Monad (PrimM a))
-            => PrimR a
-            -> Cache (PrimM a) (PrimT a)
-            -> a
-            -> (PrimM a) (Cache (PrimM a) (PrimT a))
-getRenderer rez cache a = do
-    r <- compilePrimitive rez a
-    return $ IM.insert (hash a) r cache
-
-getElementRenderer :: r -> Cache m t -> Element m r t -> m (Cache m t)
-getElementRenderer rez cache (Element a) = getRenderer rez cache a
+getRenderer :: (Hashable a, Monad m)
+            => RenderStrategy m t r a -> r -> Cache m t -> a -> m (Cache m t)
+getRenderer s rez cache a =
+    if canAllocPrimitive s rez a
+    then do r <- compilePrimitive s rez a
+            return $ IM.insert (hash a) r cache
+    else return cache
 
-clean :: Rendering m t -> m ()
+clean :: Renderer m t -> m ()
 clean = fst
 
-render :: Rendering m t -> t -> m ()
+render :: Renderer m t -> t -> m ()
 render = snd
 
-renderElement :: Monad m => Cache m t -> t -> Element m r t -> m ()
-renderElement cache t (Element a) = do
+renderElement :: (Hashable a, Monad m) => Cache m t -> t -> a -> m ()
+renderElement cache t a = do
     let k = hash a
     case IM.lookup k cache of
         Nothing -> return ()
         Just r  -> render r t
 
--- | Render a datatype using renderings stored in the given cache, return a
--- new cache that can be used to render the next datatype.
-renderData :: (Composite a m r t, Hashable a, Monad m, Monoid t)
-           => r -> Cache m t -> a -> m (Cache m t)
-renderData rez cache a = do
-        -- comp is a heterogeneous list of all the primitives needed to render
-        -- this datatype  'a'.
-    let comp = composite a
-        (found, missing) = foldl (findRenderer cache) (mempty, mempty) $ map snd comp
+-- | A sum of lists of rendering hashes between two cache states.
+-- Used for debugging resource management.
+data CacheStats a = CacheStats { cachedPrev    :: [Int]
+                               -- ^ All the keys of the previous cache state.
+                               , cachedFound   :: [Int]
+                               -- ^ The keys needed for the next state that
+                               -- were found in the previous cache (no need
+                               -- to allocate).
+                               , cachedMissing :: [Int]
+                               -- ^ The keys needed for the next state that
+                               -- were not found in the previous cache (these
+                               -- will need allocating).
+                               , cachedStale   :: [Int]
+                               -- ^ The keys found in the previous cache that
+                               -- are not needed for the next state (these
+                               -- can be deallocated).
+                               , cachedNext    :: [Int]
+                               -- ^ All the keys of the next cache state.
+                               }
+
+-- | Map a 'CacheStats' into a nice readable string.
+showCacheStats :: CacheStats a -> String
+showCacheStats (CacheStats cache found missing stale next) = unlines
+    [ "Prev:    " ++ show cache
+    , "Found:   " ++ show found
+    , "Missing: " ++ show missing
+    , "Stale:   " ++ show stale
+    , "Next:    " ++ show next
+    ]
+
+-- | Render a list of primitives using renderings stored in the given cache,
+-- return a new cache that can be used to render the next list of
+-- primitives, along with some info about the comparison of the given and
+-- returned cache.
+renderPrimsWithStats :: (Monad m, Monoid t, Hashable a)
+                     => RenderStrategy m t r a -> r -> Cache m t -> [(t, a)]
+                     -> m (Cache m t, CacheStats a)
+renderPrimsWithStats s rez cache prims = do
+    let (found, missing) = foldl (findRenderer cache)
+                                 (mempty, mempty)
+                                 (map snd prims)
         stale = cache `IM.difference` found
 
     -- Clean the stale renderers
     sequence_ $ fmap clean stale
 
     -- Get the missing renderers
-    new <- foldM (getElementRenderer rez) mempty $ IM.elems missing
+    new <- foldM (getRenderer s rez) mempty $ IM.elems missing
 
     let next = IM.union found new
-    -- Render the composite
-    mapM_ (uncurry $ renderElement next) comp
-    return next
---------------------------------------------------------------------------------
--- Instances
---------------------------------------------------------------------------------
--- | Any Element is a composite of itself if its transform type is a monoid.
-instance Monoid t => Composite (Element m r t) m r t where
-    composite e = [(mempty, e)]
+        stats = CacheStats { cachedPrev = IM.keys cache
+                           , cachedFound = IM.keys found
+                           , cachedMissing = IM.keys missing
+                           , cachedStale = IM.keys stale
+                           , cachedNext = IM.keys next
+                           }
 
--- | A tuple is a composite if its right type is a composite and the
--- left type is the transform and the transform is a Monoid. In this case the
--- result is the right type transformed by the left type.
-instance (Monoid t, Composite a m r t) => Composite (t,a) m r t where
-    composite (t, a) = map (first (mappend t)) $ composite a
+    -- Render the composite
+    mapM_ (uncurry $ renderElement next) prims
+    return (next,stats)
 
--- | A Maybe is a composite if its contained type is composite. The result
--- is is the composite of its contained type or an empty list.
-instance Composite a m r t => Composite (Maybe a) m r t where
-    composite (Just a) = composite a
-    composite _ = []
+-- | Render a list of primitives using renderings stored in the given cache,
+-- return a new cache that can be used to render the next list of
+-- primitives. Optionally print some debug info.
+renderPrimsDebug :: (MonadIO m, Monoid t, Hashable a)
+                 => Bool -> RenderStrategy m t r a -> r -> Cache m t -> [(t, a)]
+                 -> m (Cache m t)
+renderPrimsDebug debug s rez cache prims = do
+    (next, stats) <- renderPrimsWithStats s rez cache prims
+    when debug $ liftIO $ putStrLn $ showCacheStats stats
+    return next
 
--- | A list is a composite by compositing each element and concatenating
--- the result.
-instance Composite a m r t => Composite [a] m r t where
-    composite = concatMap composite
+-- | Render a list of primitives using renderings stored in the given cache,
+-- return a new cache that can be used to render the next list of
+-- primitives.
+renderPrims :: (Monad m, Monoid t, Hashable a)
+            => RenderStrategy m t r a -> r -> Cache m t -> [(t, a)]
+            -> m (Cache m t)
+renderPrims s rez cache prims = fst <$> renderPrimsWithStats s rez cache prims
