diff --git a/constraint-classes.cabal b/constraint-classes.cabal
--- a/constraint-classes.cabal
+++ b/constraint-classes.cabal
@@ -1,9 +1,9 @@
 name:
   constraint-classes
 version:
-  0.4.0
+  0.5
 synopsis:
-  Prelude classes using ConstraintKinds
+  Various typeclasses using ConstraintKinds
 description:
   Please see README.md
 homepage:
@@ -29,7 +29,9 @@
   exposed-modules:
     Control.ConstraintClasses
   build-depends:
-    base >= 4.7 && < 5
+    base >= 4.7 && < 5,
+    constraints,
+    transformers
   default-language:
     Haskell2010
 
diff --git a/src/Control/ConstraintClasses.hs b/src/Control/ConstraintClasses.hs
--- a/src/Control/ConstraintClasses.hs
+++ b/src/Control/ConstraintClasses.hs
@@ -2,113 +2,312 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
 
 module Control.ConstraintClasses
-  ( CFunctor (..)
+  (
+  -- * Constraint
+    Dom (..)
+  -- * Base classes
+  , CFunctor (..)
+  , (<$>:)
+  , CApply (..)
+  , (<*>:)
   , CApplicative (..)
   , CMonad (..)
+  , (>>=:)
+  , (=<<:)
+  , CAlt (..)
+  , (<|>:)
+  , CAlternative (..)
   , CFoldable (..)
   , CTraversable (..)
-  , CZippable (..)
-  , CIndexed (..)
+  -- * Key classes
+  , CKey (..)
+  , CLookup (..)
+  , (!?)
+  , CIndexable (..)
+  , (!)
+  , CKeyed (..)
+  , CZip (..)
+  , CZipWithKey (..)
+  , CFoldableWithKey (..)
+  , CTraversableWithKey (..)
+  , CAdjustable (..)
   ) where
 
 import GHC.Exts (Constraint)
+import Data.Constraint
+import Data.Functor.Constant
+import Data.Functor.Identity
+import Data.Functor.Product
+import Data.Functor.Sum
+import Data.Functor.Compose
 
-----------------------------------------------------------------------
+--------------------------------------------------------------------------------
 
+-- | The 'Dom' type family gives the domain of a given type constructor of kind
+-- @* -> *@. This is meant to represent that @f@ is a function from a subset of
+-- the the objects in @Hask@ to the objects of @Hask@.
+type family Dom (f :: * -> *) a :: Constraint
+
+class Any
+instance Any
+
+-- Data.Functor
+type instance Dom Identity a = Any
+type instance Dom (Product f g) a = (Dom f a, Dom g a)
+type instance Dom (Sum f g) a = (Dom f a, Dom g a)
+type instance Dom (Compose f g) a = (Dom g a, Dom f (g a))
+
+-- transformers
+type instance Dom (Constant a) b = Any
+
+--------------------------------------------------------------------------------
+
+class DomCartesian f where
+  domCartesian :: (Dom f a, Dom f b) :- Dom f (a,b)
+
+class DomCartesian f => DomClosed f where
+  domClosed :: (Dom f a, Dom f b) :- Dom f (a -> b)
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Functor@ class.
 class CFunctor f where
-  type Con f a :: Constraint
-  type Con f a = ()
+  _fmap :: (Dom f a, Dom f b) => (a -> b) -> f a -> f b
 
-  _fmap :: (Con f a, Con f b) => (a -> b) -> f a -> f b
+infixl 4 <$>:
+(<$>:) :: (CFunctor f, Dom f a, Dom f b) => (a -> b) -> f a -> f b
+(<$>:) = _fmap
 
-----------------------------------------------------------------------
+instance CFunctor (Constant a) where
+  _fmap = fmap
 
-class CFunctor f => CApplicative f where
+instance CFunctor Identity where
+  _fmap = fmap
 
-  _pure :: (Con f a) => a -> f a
+instance (CFunctor f, CFunctor g) => CFunctor (Product f g) where
+  _fmap f (Pair l r) = Pair (_fmap f l) (_fmap f r)
 
+instance (CFunctor f, CFunctor g) => CFunctor (Sum f g) where
+  _fmap f (InL x) = InL (_fmap f x)
+  _fmap f (InR x) = InR (_fmap f x)
+
+instance (CFunctor f, CFunctor g) => CFunctor (Compose f g) where
+  _fmap f (Compose x) = Compose (_fmap (_fmap f) x)
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Applicative@ class.
+class CFunctor f => CApply f where
+  _zipA ::
+    forall a b.
+    (DomCartesian f, Dom f a, Dom f b) =>
+    f a -> f b -> f (a, b)
+  _zipA x y = _liftA2 (,) x y \\ domCartesian @f @a @b
+
   _liftA2 ::
-    (Con f a, Con f b, Con f c) =>
+    (Dom f a, Dom f b, Dom f c) =>
     (a -> b -> c) -> f a -> f b -> f c
 
   _liftA3 ::
-    (Con f a, Con f b, Con f c, Con f d) =>
+    (Dom f a, Dom f b, Dom f c, Dom f d) =>
     (a -> b -> c -> d) -> f a -> f b -> f c -> f d
 
   _liftA4 ::
-    (Con f a, Con f b, Con f c, Con f d, Con f e) =>
+    (Dom f a, Dom f b, Dom f c, Dom f d, Dom f e) =>
     (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
 
-----------------------------------------------------------------------
+  _ap ::
+    (DomClosed f, Dom f a, Dom f b) =>
+    f (a -> b) -> f a -> f b
 
-class CApplicative f => CMonad f where
+infixl 4 <*>:
+(<*>:) :: (CApply f, DomClosed f, Dom f a, Dom f b) => f (a -> b) -> f a -> f b
+(<*>:) = _ap
 
+class CApply f => CApplicative f where
+  _pure :: Dom f a => a -> f a
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Monad$ class.
+class CApplicative f => CMonad f where
   _concatMap ::
-    (Con f a, Con f b) =>
+    (Dom f a, Dom f b) =>
     (a -> f b) -> f a -> f b
 
-----------------------------------------------------------------------
+infixl 1 >>=:
+(>>=:) :: (CMonad f, Dom f a, Dom f b) => f a -> (a -> f b) -> f b
+(>>=:) = flip _concatMap
 
+infixr 1 =<<:
+(=<<:) :: (CMonad f, Dom f a, Dom f b) => (a -> f b) -> f a -> f b
+(=<<:) = _concatMap
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Applicative@ class.
+class CApplicative f => CAlt f where
+  _concat :: Dom f a => f a -> f a -> f a
+
+infixl 3 <|>:
+(<|>:) :: (CAlt f, Dom f a) => f a -> f a -> f a
+(<|>:) = _concat
+
+class CAlt f => CAlternative f where
+  _empty :: Dom f a => f a
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Foldable@ class.
 class CFoldable f where
   {-# MINIMAL _foldMap | _foldr #-}
 
-  _foldr  :: (Con f a) => (a -> b -> b) -> b -> f a -> b
-  _foldr' :: (Con f a) => (a -> b -> b) -> b -> f a -> b
-  _foldl  :: (Con f b) => (a -> b -> a) -> a -> f b -> a
-  _foldl' :: (Con f b) => (a -> b -> a) -> a -> f b -> a
+  _foldr  :: Dom f a => (a -> b -> b) -> b -> f a -> b
+  _foldr' :: Dom f a => (a -> b -> b) -> b -> f a -> b
+  _foldl  :: Dom f b => (a -> b -> a) -> a -> f b -> a
+  _foldl' :: Dom f b => (a -> b -> a) -> a -> f b -> a
 
-  _fold :: (Con f m, Monoid m) => f m -> m
+  _fold :: (Dom f m, Monoid m) => f m -> m
   _fold = _foldMap id
 
-  _foldMap :: (Con f a, Con f m, Monoid m) => (a -> m) -> f a -> m
+  _foldMap :: (Dom f a, Monoid m) => (a -> m) -> f a -> m
   _foldMap f = _foldr (mappend . f) mempty
   {-# INLINE _foldMap #-}
 
-  _length :: Con f a => f a -> Int
-  _length = _foldl (\c _ -> c+1) 0
-
-  _mapM :: (Monad m, Con f a, Con f b)
-        => (a -> m b) -> f a -> m (f b)
+  _toList :: Dom f a => f a -> [a]
+  _toList = _foldr (:) []
 
-  _forM :: (Monad m, Con f a, Con f b)
-        => f a -> (a -> m b) -> m (f b)
-  _forM = flip _mapM
+  _length :: Dom f a => f a -> Int
+  _length = _foldl (\c _ -> c+1) 0
 
-  _mapM_ :: (Monad m, Con f a)
-         => (a -> m b) -> f a -> m ()
+  _mapM_ ::
+    (Monad m, Dom f a) =>
+    (a -> m b) -> f a -> m ()
+  _mapM_ f = _foldr ((>>) . f) (return ())
 
-  _forM_ :: (Monad m, Con f a)
-         => f a -> (a -> m b) -> m ()
+  _forM_ ::
+    (Monad m, Dom f a) =>
+    f a -> (a -> m b) -> m ()
   _forM_ = flip _mapM_
 
-----------------------------------------------------------------------
+--------------------------------------------------------------------------------
 
+-- | Equivalent to the @Traversable@ class.
 class (CFunctor t, CFoldable t) => CTraversable t where
-
   _traverse ::
-    (Con t a, Con t b, Monad f) =>
+    (Dom t a, Dom t b, Monad f) =>
     (a -> f b) -> t a -> f (t b)
 
-----------------------------------------------------------------------
+  _sequence ::
+    (Monad f, Dom t a, Dom t (f a)) =>
+    t (f a) -> f (t a)
+  _sequence = _traverse id
 
-class CFunctor f => CZippable f where
+--------------------------------------------------------------------------------
 
+-- | Equivalent to the @Zip@ class.
+class CFunctor f => CZip f where
+  _zip ::
+    (DomCartesian f, Dom f a, Dom f b) =>
+    f a -> f b -> f (a, b)
+
   _zipWith ::
-    (Con f a, Con f b, Con f c) =>
+    (Dom f a, Dom f b, Dom f c) =>
     (a -> b -> c) -> f a -> f b -> f c
 
   _zipWith3 ::
-    (Con f a, Con f b, Con f c, Con f d) =>
+    (Dom f a, Dom f b, Dom f c, Dom f d) =>
     (a -> b -> c -> d) -> f a -> f b -> f c -> f d
 
   _zipWith4 ::
-    (Con f a, Con f b, Con f c, Con f d, Con f e) =>
+    (Dom f a, Dom f b, Dom f c, Dom f d, Dom f e) =>
     (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
 
-----------------------------------------------------------------------
+  _zipAp ::
+    (DomClosed f, Dom f a, Dom f b) =>
+    f (a -> b) -> f a -> f b
 
-class CFunctor f => CIndexed f i | f -> i where
+--------------------------------------------------------------------------------
 
-  (!) :: (Con f a) => f a -> i -> a
+-- | Equivalent to the @Key@ type family.
+type family CKey (f :: * -> *)
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Lookup@ class.
+class CLookup f where
+  _lookup :: Dom f a => CKey f -> f a -> Maybe a
+
+(!?) :: (CLookup f, Dom f a) => CKey f -> f a -> Maybe a
+(!?) = _lookup
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Indexable@ class.
+class CLookup f => CIndexable f where
+  _index :: Dom f a => f a -> CKey f -> a
+
+(!) :: (CIndexable f, Dom f a) => f a -> CKey f -> a
+(!) = _index
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Keyed@ class.
+class CFunctor f => CKeyed f where
+   _imap ::
+     (Dom f a, Dom f b) =>
+     (CKey f -> a -> b) -> f a -> f b
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Zip@ class.
+class (CKeyed f, CZip f) => CZipWithKey f where
+  _izipWith ::
+    (Dom f a, Dom f b, Dom f c) =>
+    (CKey f -> a -> b -> c) -> f a -> f b -> f c
+
+  _izipWith3 ::
+    (Dom f a, Dom f b, Dom f c, Dom f d) =>
+    (CKey f -> a -> b -> c -> d) -> f a -> f b -> f c -> f d
+
+  _izipWith4 ::
+    (Dom f a, Dom f b, Dom f c, Dom f d, Dom f e) =>
+    (CKey f -> a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @FoldableWithKey@ class.
+class CFoldable f => CFoldableWithKey f where
+  _itoList :: Dom f a => f a -> [(CKey f, a)]
+  _ifoldMap :: (Monoid m, Dom f a) => (CKey f -> a -> m) -> f a -> m
+  _ifoldr :: Dom f a => (CKey f -> a -> b -> b) -> b -> f a -> b
+  _ifoldr' :: Dom f a => (CKey f -> a -> b -> b) -> b -> f a -> b
+  _ifoldl :: Dom f b => (a -> CKey f -> b -> a) -> a -> f b -> a
+  _ifoldl' :: Dom f b => (a -> CKey f -> b -> a) -> a -> f b -> a
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Adjustable@ class.
+class CFunctor f => CAdjustable f where
+  _update :: Dom f a => (a -> b -> a) -> f a -> [(CKey f, b)] -> f a
+  _adjust :: Dom f a => (a -> a) -> CKey f -> f a -> f a
+  _adjust f n v = _update (\a _ -> f a) v [(n,())]
+  _replace :: Dom f a => CKey f -> a -> f a -> f a
+  _replace n x = _adjust (const x) n
+
+--------------------------------------------------------------------------------
+
+-- | Equivalent to the @Traversable@ class.
+class (CKeyed t, CFoldableWithKey t, CTraversable t) =>
+  CTraversableWithKey t where
+  _itraverse ::
+    (Dom t a, Dom t b, Monad f) =>
+    (CKey t -> a -> f b) -> t a -> f (t b)
