diff --git a/quantification.cabal b/quantification.cabal
--- a/quantification.cabal
+++ b/quantification.cabal
@@ -1,5 +1,5 @@
 name:                quantification
-version:             0.1
+version:             0.1.1
 synopsis:            Data types and typeclasses to deal with universally and existentially quantified types
 description:         Please see README.md
 homepage:            https://github.com/andrewthad/quantification#readme
@@ -17,7 +17,7 @@
   exposed-modules:
     Data.Exists
   build-depends: 
-      base >= 4.7 && < 5
+      base >= 4.9 && < 5
     , hashable >= 1.2 && < 1.3
     , aeson >= 0.11 && < 1.2
     , text >= 1.0 && < 2.0
diff --git a/src/Data/Exists.hs b/src/Data/Exists.hs
--- a/src/Data/Exists.hs
+++ b/src/Data/Exists.hs
@@ -4,17 +4,56 @@
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE CPP #-}
-module Data.Exists where
 
+{-# OPTIONS_GHC -Wall #-}
+
+{-| Data types and type classes for working with existentially quantified
+    values. In the event that Quantified Class Constraints ever land in GHC,
+    this package will be considered obsolete. The benefit that most of the
+    typeclasses in this module provide is that they help populate the instances
+    of 'Exists'.
+-}
+
+module Data.Exists
+  ( -- * Data Types
+    Exists(..)
+  , Exists2(..)
+  , Exists3(..)
+    -- * Type Classes
+  , EqForall(..)
+  , EqForallPoly(..)
+  , OrdForall(..)
+  , OrdForallPoly(..)
+  , ShowForall(..)
+  , ReadForall(..)
+  , EnumForall(..)
+  , BoundedForall(..)
+  , MonoidForall(..)
+  , HashableForall(..)
+  , PathPieceForall(..)
+#if MIN_VERSION_aeson(1,0,0) 
+  , ToJSONKeyForall(..)
+  , FromJSONKeyForall(..)
+#endif
+    -- * Higher Rank Classes
+  , EqForall2(..)
+  , EqForallPoly2(..)
+    -- * Functions
+  , showsForall
+  , showForall
+  ) where
+
 import Data.Proxy (Proxy(..))
 import Data.Type.Equality ((:~:)(Refl))
 import Control.Applicative (Const(..))
 import Data.Aeson (ToJSON(..),FromJSON(..))
 import Data.Hashable (Hashable(..))
 import Data.Text (Text)
+import Data.Functor.Sum (Sum(..))
+import Data.Functor.Product (Product(..))
+import Data.Functor.Compose (Compose(..))
 import qualified Data.Aeson.Types as Aeson
 import qualified Text.Read as R
-import qualified Text.Read.Lex as R
 import qualified Web.PathPieces as PP
 
 #if MIN_VERSION_aeson(1,0,0) 
@@ -25,8 +64,11 @@
 
 -- newtype Exists (f :: k -> *) = Exists { runExists :: forall r. (forall a. f a -> r) -> r }
 
+-- | Hide a type parameter.
 data Exists (f :: k -> *) = forall a. Exists !(f a)
+
 data Exists2 (f :: k -> j -> *) = forall a b. Exists2 !(f a b)
+
 data Exists3 (f :: k -> j -> l -> *) = forall a b c. Exists3 !(f a b c)
 
 #if MIN_VERSION_aeson(1,0,0) 
@@ -191,5 +233,39 @@
   toPathPiece (Exists f) = toPathPieceForall f
   fromPathPiece = fromPathPieceForall
 
+instance (EqForall f, EqForall g) => EqForall (Product f g) where
+  eqForall (Pair f1 g1) (Pair f2 g2) = eqForall f1 f2 && eqForall g1 g2
+
+instance (EqForallPoly f, EqForallPoly g) => EqForallPoly (Product f g) where
+  eqForallPoly (Pair f1 g1) (Pair f2 g2) = eqForallPoly f1 f2 && eqForallPoly g1 g2
+
+instance (OrdForall f, OrdForall g) => OrdForall (Product f g) where
+  compareForall (Pair f1 g1) (Pair f2 g2) = mappend (compareForall f1 f2) (compareForall g1 g2)
+
+instance (OrdForallPoly f, OrdForallPoly g) => OrdForallPoly (Product f g) where
+  compareForallPoly (Pair f1 g1) (Pair f2 g2) = mappend (compareForallPoly f1 f2) (compareForallPoly g1 g2)
+
+instance (ShowForall f, ShowForall g) => ShowForall (Product f g) where
+  showsPrecForall p (Pair f g) = showParen 
+    (p >= 11) 
+    (showString "Pair " . showsPrecForall 11 f . showChar ' ' . showsPrecForall 11 g)
+
+instance (EqForall f) => EqForall (Compose f g) where
+  eqForall (Compose x) (Compose y) = eqForall x y
+
+instance (EqForallPoly f) => EqForallPoly (Compose f g) where
+  eqForallPoly (Compose x) (Compose y) = eqForallPoly x y
+
+instance (EqForall f, EqForall g) => EqForall (Sum f g) where
+  eqForall (InL f1) (InL f2) = eqForall f1 f2
+  eqForall (InR f1) (InR f2) = eqForall f1 f2
+  eqForall (InR _) (InL _) = False
+  eqForall (InL _) (InR _) = False
+
+instance (OrdForall f, OrdForall g) => OrdForall (Sum f g) where
+  compareForall (InL f1) (InL f2) = compareForall f1 f2
+  compareForall (InR f1) (InR f2) = compareForall f1 f2
+  compareForall (InR _) (InL _) = GT
+  compareForall (InL _) (InR _) = LT
 
 
