diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,20 @@
+0.0.5
+
+* Generalise instances from concrete `(->)` to a polymorphic profunctor
+  parameter `p` wherever the implementation only requires profunctor
+  operations (`rmap`, `lmap`, `dimap`) rather than function application:
+  - `Functor (Kleisli p a f)` — requires `Profunctor p`
+  - `Functor (ProKleisli p f a)` — requires `Profunctor p`
+  - `Profunctor (ProKleisli p f)` — requires `Profunctor p`
+  - `Contravariant (ContraKleisli p b f)` — requires `Profunctor p`
+  - `Strong (ProKleisli p f)` — requires `Strong p`
+  - `Choice (ProKleisli p f)` — requires `Choice p`
+  - `Closed (ProKleisli p f)` — requires `Closed p`
+  - `Traversing (ProKleisli p f)` — requires `Traversing p`
+  - `Mapping (ProKleisli p f)` — requires `Mapping p`
+  - `Sieve (ProKleisli p f) (Compose g f)` — requires `Sieve p g`
+  - `PRep.Representable (ProKleisli p f)` — requires `PRep.Representable p`
+
 0.0.4
 
 * Add `fromMaybe` for replacing Nothing results with a default value,
diff --git a/kleisli.cabal b/kleisli.cabal
--- a/kleisli.cabal
+++ b/kleisli.cabal
@@ -1,6 +1,6 @@
 cabal-version:        2.4
 name:                 kleisli
-version:              0.0.4
+version:              0.0.5
 synopsis:             Kleisli-like newtypes with different type parameter orderings
 description:
   Three newtype wrappers around @p a (f b)@ with different type parameter
diff --git a/src/Data/Kleisli.hs b/src/Data/Kleisli.hs
--- a/src/Data/Kleisli.hs
+++ b/src/Data/Kleisli.hs
@@ -99,6 +99,7 @@
 import Control.Monad.Zip (MonadZip)
 import Control.Selective (Selective)
 import Data.Distributive (Distributive (..))
+import Data.Functor.Compose (Compose (..))
 import Data.Functor.Alt (Alt (..))
 import Data.Functor.Apply (Apply (..))
 import Data.Functor.Bind (Bind (..))
@@ -113,13 +114,13 @@
 import Data.Functor.Plus (Plus (..))
 import qualified Data.Functor.Rep as FRep (Rep, Representable (..))
 import qualified Data.Maybe as Maybe
-import Data.Profunctor (Closed, Strong)
+import Data.Profunctor (Closed (..), Strong (..))
 import Data.Profunctor.Choice (Cochoice)
-import Data.Profunctor.Mapping (Mapping)
+import Data.Profunctor.Mapping (Mapping (..))
 import qualified Data.Profunctor.Rep as PRep (Representable (..))
 import Data.Profunctor.Sieve (Sieve (..))
 import Data.Profunctor.Strong (Costrong)
-import Data.Profunctor.Traversing (Traversing)
+import Data.Profunctor.Traversing (Traversing (..))
 import Data.Profunctor.Types (Star (..))
 import Data.Semigroupoid (Semigroupoid)
 import GHC.Generics (Generic)
@@ -459,8 +460,8 @@
 
 -- | >>> let Kleisli f = fmap (+1) (Kleisli Just) in f 5
 -- Just 6
-instance (Functor f) => Functor (Kleisli (->) a f) where
-  fmap g (Kleisli k) = Kleisli (fmap g . k)
+instance (Profunctor p, Functor f) => Functor (Kleisli p a f) where
+  fmap g (Kleisli k) = Kleisli (rmap (fmap g) k)
   {-# INLINE fmap #-}
 
 -- | >>> let Kleisli f = pure 42 :: Kleisli (->) String Maybe Int in f "ignored"
@@ -603,9 +604,9 @@
   distribute gs = Kleisli (\a -> distribute (fmap (\(Kleisli k) -> k a) gs))
   {-# INLINE distribute #-}
 
--- | >>> import Data.Functor.Rep (index)
+-- | >>> import qualified Data.Functor.Rep as FRep (index)
 -- >>> let k = Kleisli (\a -> Identity (a * 2)) :: Kleisli (->) Int Identity Int
--- >>> index k (3, ())
+-- >>> FRep.index k (3, ())
 -- 6
 instance (FRep.Representable f) => FRep.Representable (Kleisli (->) a f) where
   type Rep (Kleisli (->) a f) = (a, FRep.Rep f)
@@ -641,8 +642,8 @@
 
 -- | >>> let ProKleisli f = fmap (+1) (ProKleisli Just) in f 5
 -- Just 6
-instance (Functor f) => Functor (ProKleisli (->) f a) where
-  fmap g (ProKleisli k) = ProKleisli (fmap g . k)
+instance (Profunctor p, Functor f) => Functor (ProKleisli p f a) where
+  fmap g (ProKleisli k) = ProKleisli (rmap (fmap g) k)
   {-# INLINE fmap #-}
 
 -- | >>> let ProKleisli f = pure 42 :: ProKleisli (->) Maybe String Int in f "ignored"
@@ -777,9 +778,9 @@
   distribute gs = ProKleisli (\a -> distribute (fmap (\(ProKleisli k) -> k a) gs))
   {-# INLINE distribute #-}
 
--- | >>> import Data.Functor.Rep (index)
+-- | >>> import qualified Data.Functor.Rep as FRep (index)
 -- >>> let k = ProKleisli (\a -> Identity (a * 2)) :: ProKleisli (->) Identity Int Int
--- >>> index k (3, ())
+-- >>> FRep.index k (3, ())
 -- 6
 instance (FRep.Representable f) => FRep.Representable (ProKleisli (->) f a) where
   type Rep (ProKleisli (->) f a) = (a, FRep.Rep f)
@@ -793,23 +794,27 @@
 --
 -- >>> let ProKleisli f = rmap (+1) (ProKleisli Just :: ProKleisli (->) Maybe Int Int) in f 5
 -- Just 6
-instance (Functor f) => Profunctor (ProKleisli (->) f) where
-  dimap f g (ProKleisli k) = ProKleisli (fmap g . k . f)
+instance (Profunctor p, Functor f) => Profunctor (ProKleisli p f) where
+  dimap f g (ProKleisli k) = ProKleisli (dimap f (fmap g) k)
   {-# INLINE dimap #-}
-  lmap f (ProKleisli k) = ProKleisli (k . f)
+  lmap f (ProKleisli k) = ProKleisli (lmap f k)
   {-# INLINE lmap #-}
-  rmap g (ProKleisli k) = ProKleisli (fmap g . k)
+  rmap g (ProKleisli k) = ProKleisli (rmap (fmap g) k)
   {-# INLINE rmap #-}
 
 -- | >>> import Data.Profunctor (Strong(..))
 -- >>> let ProKleisli f = first' (ProKleisli Just :: ProKleisli (->) Maybe Int Int) in f (5, "hi")
 -- Just (5,"hi")
-deriving via (Star f) instance (Functor f) => Strong (ProKleisli (->) f)
+instance (Strong p, Functor f) => Strong (ProKleisli p f) where
+  first' (ProKleisli k) = ProKleisli (rmap (\(fb, c) -> fmap (\b -> (b, c)) fb) (first' k))
+  {-# INLINE first' #-}
 
 -- | >>> import Data.Profunctor.Choice (Choice(..))
 -- >>> let ProKleisli f = left' (ProKleisli Just :: ProKleisli (->) Maybe Int Int) in f (Left 5)
 -- Just (Left 5)
-deriving via (Star f) instance (Applicative f) => Choice (ProKleisli (->) f)
+instance (Choice p, Applicative f) => Choice (ProKleisli p f) where
+  left' (ProKleisli k) = ProKleisli (rmap (either (fmap Left) (pure . Right)) (left' k))
+  {-# INLINE left' #-}
 
 -- | >>> import Data.Profunctor.Choice (Cochoice(..))
 -- >>> let ProKleisli f = unleft (ProKleisli (\e -> [e]) :: ProKleisli (->) [] (Either Int ()) (Either Int ())) in f 5
@@ -820,33 +825,41 @@
 -- >>> import Data.Functor.Identity (Identity(..))
 -- >>> let ProKleisli f = closed (ProKleisli (Identity . (+1)) :: ProKleisli (->) Identity Int Int) in runIdentity (f (const 5)) ()
 -- 6
-deriving via (Star f) instance (Distributive f) => Closed (ProKleisli (->) f)
+instance (Closed p, Distributive f) => Closed (ProKleisli p f) where
+  closed (ProKleisli k) = ProKleisli (rmap distribute (closed k))
+  {-# INLINE closed #-}
 
 -- | >>> import Data.Profunctor.Traversing (Traversing(..))
 -- >>> let ProKleisli f = traverse' (ProKleisli Just :: ProKleisli (->) Maybe Int Int) in f [1,2,3]
 -- Just [1,2,3]
-deriving via (Star f) instance (Applicative f) => Traversing (ProKleisli (->) f)
+instance (Traversing p, Applicative f) => Traversing (ProKleisli p f) where
+  traverse' (ProKleisli k) = ProKleisli (rmap sequenceA (traverse' k))
+  {-# INLINE traverse' #-}
 
 -- | >>> import Data.Profunctor.Mapping (Mapping(..))
 -- >>> import Data.Functor.Identity (Identity(..))
 -- >>> let ProKleisli f = map' (ProKleisli (Identity . (+1)) :: ProKleisli (->) Identity Int Int) in f [1,2,3]
 -- Identity [2,3,4]
-deriving via (Star f) instance (Applicative f, Distributive f) => Mapping (ProKleisli (->) f)
+instance (Mapping p, Applicative f, Distributive f) => Mapping (ProKleisli p f) where
+  map' (ProKleisli k) = ProKleisli (rmap distribute (map' k))
+  {-# INLINE map' #-}
 
 -- | >>> import Data.Profunctor.Sieve (sieve)
+-- >>> import Data.Functor.Compose (Compose(..))
 -- >>> sieve (ProKleisli Just :: ProKleisli (->) Maybe Int Int) 5
--- Just 5
-instance (Functor f) => Sieve (ProKleisli (->) f) f where
-  sieve (ProKleisli f) = f
+-- Compose (Identity (Just 5))
+instance (Sieve p g, Functor g, Functor f) => Sieve (ProKleisli p f) (Compose g f) where
+  sieve (ProKleisli k) = Compose . sieve k
   {-# INLINE sieve #-}
 
 -- | >>> import qualified Data.Profunctor.Rep as PRep (tabulate)
 -- >>> import Data.Functor.Identity (Identity(..))
--- >>> let ProKleisli f = PRep.tabulate Identity :: ProKleisli (->) Identity Int Int in f 5
+-- >>> import Data.Functor.Compose (Compose(..))
+-- >>> let ProKleisli f = PRep.tabulate (Compose . Identity . Identity) :: ProKleisli (->) Identity Int Int in f 5
 -- Identity 5
-instance (Functor f, Distributive f) => PRep.Representable (ProKleisli (->) f) where
-  type Rep (ProKleisli (->) f) = f
-  tabulate = ProKleisli
+instance (PRep.Representable p, Distributive (PRep.Rep p), Functor f, Distributive f) => PRep.Representable (ProKleisli p f) where
+  type Rep (ProKleisli p f) = Compose (PRep.Rep p) f
+  tabulate f = ProKleisli (PRep.tabulate (getCompose . f))
   {-# INLINE tabulate #-}
 
 -- | >>> import Data.Profunctor.Strong (Costrong(..))
@@ -922,8 +935,8 @@
 -- | >>> import Data.Functor.Contravariant (contramap)
 -- >>> let ContraKleisli f = contramap (+1) (ContraKleisli Just :: ContraKleisli (->) Int Maybe Int) in f 5
 -- Just 6
-instance Contravariant (ContraKleisli (->) b f) where
-  contramap f (ContraKleisli k) = ContraKleisli (k . f)
+instance (Profunctor p) => Contravariant (ContraKleisli p b f) where
+  contramap f (ContraKleisli k) = ContraKleisli (lmap f k)
   {-# INLINE contramap #-}
 
 -- | >>> import Data.Functor.Contravariant.Divisible (divide, conquer)
