diff --git a/profunctor-extras.cabal b/profunctor-extras.cabal
--- a/profunctor-extras.cabal
+++ b/profunctor-extras.cabal
@@ -1,6 +1,6 @@
 name:             profunctor-extras
 category:         Control, Categories
-version:          3.1
+version:          3.2
 license:          BSD3
 cabal-version:    >= 1.6
 license-file:     LICENSE
@@ -29,10 +29,12 @@
   hs-source-dirs: src
 
   other-extensions:
+    CPP
     GADTs
+    FlexibleContexts
     FlexibleInstances
     UndecidableInstances
-    MultiParamTypeClasses
+    TypeFamilies
 
   build-depends:
     base                == 4.*,
diff --git a/src/Data/Profunctor/Composition.hs b/src/Data/Profunctor/Composition.hs
--- a/src/Data/Profunctor/Composition.hs
+++ b/src/Data/Profunctor/Composition.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeFamilies #-}
 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE Trustworthy #-}
 #endif
@@ -31,6 +32,7 @@
 import Control.Monad (liftM)
 import Data.Functor.Compose
 import Data.Profunctor
+import Data.Profunctor.Rep
 import Data.Profunctor.Unsafe
 
 -- * Profunctor Composition
@@ -52,6 +54,17 @@
 
 instance Profunctor q => Functor (Procompose p q a) where
   fmap k (Procompose f g) = Procompose f (rmap k g)
+
+-- | The composition of two representable profunctors is representable by the composition of their representations.
+instance (Representable p, Representable q) => Representable (Procompose p q) where
+  type Rep (Procompose p q) = Compose (Rep p) (Rep q)
+  tabulate f = Procompose (tabulate (getCompose . f)) (tabulate id)
+  rep (Procompose f g) d = Compose $ rep g <$> rep f d
+
+instance (Corepresentable p, Corepresentable q) => Corepresentable (Procompose p q) where
+  type Corep (Procompose p q) = Compose (Corep q) (Corep p)
+  cotabulate f = Procompose (cotabulate id) (cotabulate (f . Compose))
+  corep (Procompose f g) (Compose d) = corep g $ corep f <$> d
 
 -- * Lax identity
 
diff --git a/src/Data/Profunctor/Rep.hs b/src/Data/Profunctor/Rep.hs
--- a/src/Data/Profunctor/Rep.hs
+++ b/src/Data/Profunctor/Rep.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
@@ -11,23 +10,21 @@
 --
 -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
 -- Stability   :  provisional
--- Portability :  MPTCs
+-- Portability :  Type-Families
 --
 ----------------------------------------------------------------------------
 module Data.Profunctor.Rep
   (
   -- * Representable Profunctors
-    Rep(..), tabulated
+    Representable(..), tabulated
   -- * Corepresentable Profunctors
-  , Corep(..), cotabulated
+  , Corepresentable(..), cotabulated
   ) where
 
 import Control.Arrow
 import Control.Comonad
-import Data.Functor.Compose
 import Data.Functor.Identity
 import Data.Profunctor
-import Data.Profunctor.Composition
 import Data.Proxy
 import Data.Tagged
 
@@ -35,71 +32,71 @@
 
 -- | A 'Profunctor' @p@ is representable if there exists a 'Functor' @f@ such that
 -- @p d c@ is isomorphic to @d -> f c@.
-class (Functor f, Profunctor p) => Rep f p where
-  tabulate :: (d -> f c) -> p d c
-  rep :: p d c -> d -> f c
+class (Functor (Rep p), Profunctor p) => Representable p where
+  type Rep p :: * -> *
+  tabulate :: (d -> Rep p c) -> p d c
+  rep :: p d c -> d -> Rep p c
 
-instance Rep Identity (->) where
+instance Representable (->) where
+  type Rep (->) = Identity
   tabulate f = runIdentity . f
   rep f = Identity . f
 
-instance (Monad m, Functor m) => Rep m (Kleisli m) where
+instance (Monad m, Functor m) => Representable (Kleisli m) where
+  type Rep (Kleisli m) = m
   tabulate = Kleisli
   rep = runKleisli
 
-instance Functor f => Rep f (UpStar f) where
+instance Functor f => Representable (UpStar f) where
+  type Rep (UpStar f) = f
   tabulate = UpStar
   rep = runUpStar
 
--- | The composition of two representable profunctors is representable by the composition of their representations.
-instance (Rep f p, Rep g q) => Rep (Compose f g) (Procompose p q) where
-  tabulate f = Procompose (tabulate (getCompose . f)) (tabulate id)
-  rep (Procompose f g) d = Compose $ rep g <$> rep f d
-
 -- | 'tabulate' and 'rep' form two halves of an isomorphism.
 --
 -- This can be used with the combinators from the @lens@ package.
 --
--- @'tabulated' :: 'Rep' f p => 'Iso'' (d -> f c) (p d c)@
-tabulated :: (Profunctor r, Functor h, Rep f p, Rep g q)
-          => r (p d c) (h (q d' c'))
-          -> r (d -> f c) (h (d' -> g c'))
+-- @'tabulated' :: 'Representable' p => 'Iso'' (d -> 'Rep' p c) (p d c)@
+tabulated :: (Profunctor r, Functor f, Representable p, Representable q)
+          => r (p d c) (f (q d' c'))
+          -> r (d -> Rep p c) (f (d' -> Rep q c'))
 tabulated = dimap tabulate (fmap rep)
 
 -- * Corepresentable Profunctors
 
--- | A 'Profunctor' @p@ is representable if there exists a 'Functor' @f@ such that
--- @p d c@ is isomorphic to @d -> f c@.
-class (Functor f, Profunctor p) => Corep f p where
-  cotabulate :: (f d -> c) -> p d c
-  corep :: p d c -> f d -> c
+-- | A 'Profunctor' @p@ is corepresentable if there exists a 'Functor' @f@ such that
+-- @p d c@ is isomorphic to @f d -> c@.
+class (Functor (Corep p), Profunctor p) => Corepresentable p where
+  type Corep p :: * -> *
+  cotabulate :: (Corep p d -> c) -> p d c
+  corep :: p d c -> Corep p d -> c
 
-instance Corep Identity (->) where
+instance Corepresentable (->) where
+  type Corep (->) = Identity
   cotabulate f = f . Identity
   corep f (Identity d) = f d
 
-instance Functor w => Corep w (Cokleisli w) where
+instance Functor w => Corepresentable (Cokleisli w) where
+  type Corep (Cokleisli w) = w
   cotabulate = Cokleisli
   corep = runCokleisli
 
-instance Corep Proxy Tagged where
+instance Corepresentable Tagged where
+  type Corep Tagged = Proxy
   cotabulate f = Tagged (f Proxy)
   corep (Tagged a) _ = a
 
-instance Functor f => Corep f (DownStar f) where
+instance Functor f => Corepresentable (DownStar f) where
+  type Corep (DownStar f) = f
   cotabulate = DownStar
   corep = runDownStar
 
-instance (Corep f p, Corep g q) => Corep (Compose g f) (Procompose p q) where
-  cotabulate f = Procompose (cotabulate id) (cotabulate (f . Compose))
-  corep (Procompose f g) (Compose d) = corep g $ corep f <$> d
-
 -- | 'cotabulate' and 'corep' form two halves of an isomorphism.
 --
 -- This can be used with the combinators from the @lens@ package.
 --
 -- @'tabulated' :: 'Corep' f p => 'Iso'' (f d -> c) (p d c)@
-cotabulated :: (Profunctor r, Functor h, Corep f p, Corep g q)
+cotabulated :: (Profunctor r, Functor h, Corepresentable p, Corepresentable q)
           => r (p d c) (h (q d' c'))
-          -> r (f d -> c) (h (g d' -> c'))
+          -> r (Corep p d -> c) (h (Corep q d' -> c'))
 cotabulated = dimap cotabulate (fmap corep)
