diff --git a/Control/Comonad/Indexed/Trans/Costate.hs b/Control/Comonad/Indexed/Trans/Costate.hs
new file mode 100644
--- /dev/null
+++ b/Control/Comonad/Indexed/Trans/Costate.hs
@@ -0,0 +1,28 @@
+-- | The indexed costate (also called "store") transfomer: each @'CostateT' f i j@ term has a value of type @i@, and wants within @f@ a value of type @j@.
+
+module Control.Comonad.Indexed.Trans.Costate where
+
+import Prelude hiding ((.))
+import qualified Control.Applicative as Base
+import qualified Control.Comonad as Base
+import Control.Semigroupoid
+import Data.Functor.Indexed
+
+data CostateT f i j a = CostateT (f (j -> a)) i
+  deriving (Functor)
+
+colift :: Functor f => CostateT f k k a -> f a
+colift (CostateT x s) = ($ s) <$> x
+
+lens :: Functor φ => ((f (j -> a), i) -> φ (g (v -> b), u)) -> CostateT f i j a -> φ (CostateT g u v b)
+lens φ (CostateT x s) = uncurry CostateT <$> φ (x, s)
+
+instance Base.Applicative p => Apply (CostateT p) where
+    liftA2 φ (CostateT x i) (CostateT y j) = CostateT (Base.liftA2 (\ f g -> φ (f j) . g) x y) i
+
+instance (Base.Comonad ɯ) => Cobind (CostateT ɯ) where
+    cut (CostateT f i) = CostateT (CostateT f <$ f) i
+
+instance (Base.Comonad ɯ) => Base.Comonad (CostateT ɯ k k) where
+    copure (CostateT f i) = copure f i
+    cut = cut
diff --git a/Control/Comonad/Indexed/Trans/Cowriter.hs b/Control/Comonad/Indexed/Trans/Cowriter.hs
new file mode 100644
--- /dev/null
+++ b/Control/Comonad/Indexed/Trans/Cowriter.hs
@@ -0,0 +1,37 @@
+-- | The indexed cowriter transformer: each @'CowriterT' κ f@ term wants within @f@ a morphism of @κ@.
+
+module Control.Comonad.Indexed.Trans.Cowriter where
+
+import Prelude hiding ((.), id)
+import qualified Control.Applicative as Base
+import Control.Category hiding ((.))
+import qualified Control.Comonad as Base
+import qualified Control.Monad as Base
+import Control.Semigroupoid
+import Data.Functor.Indexed
+
+newtype CowriterT κ f i j a = CowriterT { runCowriterT :: f (κ i j -> a) }
+  deriving (Functor)
+
+instance Base.Applicative p => Base.Applicative (CowriterT κ p i j) where
+    pure = CowriterT . pure . pure
+    CowriterT x <*> CowriterT y = CowriterT (Base.liftA2 (Base.<*>) x y)
+
+instance (Base.Comonad ɯ, Category κ) => Base.Comonad (CowriterT κ ɯ k k) where
+    copure = cotell id
+    cut = cut
+
+instance (Base.Comonad ɯ, Semigroupoid κ) => Cobind (CowriterT κ ɯ) where
+    cut = mapCowriterT (Base.=>> \ ɯ s -> CowriterT $ (. (. s)) <$> ɯ)
+
+mapCowriterT :: (f (κ i j -> a) -> g (κ' u v -> b)) -> CowriterT κ f i j a -> CowriterT κ' g u v b
+mapCowriterT f = CowriterT . f . runCowriterT
+
+cotell :: Base.Comonad ɯ => κ i j -> CowriterT κ ɯ i j a -> a
+cotell κ = ($ κ) . copure . runCowriterT
+
+listen :: Functor f => CowriterT κ f i j a -> CowriterT κ f i j (a, κ i j)
+listen = (mapCowriterT . fmap) (Base.>>= (,))
+
+censor :: Functor f => (κ' u v -> κ i j) -> CowriterT κ f i j a -> CowriterT κ' f u v a
+censor = mapCowriterT . fmap . flip (.)
diff --git a/Control/Monad/Indexed/Signatures.hs b/Control/Monad/Indexed/Signatures.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Indexed/Signatures.hs
@@ -0,0 +1,9 @@
+module Control.Monad.Indexed.Signatures where
+
+type CallCC f g h a b c d = ((a -> f b) -> g c) -> h d
+
+type Catch e f g h a b c = f a -> (e -> g b) -> h c
+
+type Listen w f a b = b -> f (a, w)
+
+type Pass z f g a b = f (a, z) -> g b
diff --git a/Control/Monad/Indexed/Trans/Cont.hs b/Control/Monad/Indexed/Trans/Cont.hs
--- a/Control/Monad/Indexed/Trans/Cont.hs
+++ b/Control/Monad/Indexed/Trans/Cont.hs
@@ -1,19 +1,22 @@
+-- | The indexed continuation transformer: see 'ContT'.
+
 module Control.Monad.Indexed.Trans.Cont where
 
-import Prelude (Functor (..), flip, ($))
-import Control.Applicative
+import Prelude (Functor (..), flip, ($), (<$>))
+import Control.Applicative (Alternative (..))
+import qualified Control.Applicative as Base
 import Control.Category
-import Control.Monad (Monad ((>>=)), MonadPlus (..))
-import Control.Monad.Fail (MonadFail (..))
+import qualified Control.Monad as Base
+import qualified Control.Monad.Fail as Base
 import Data.Functor.Indexed
 
 newtype ContT f i j a = ContT { runContT :: (a -> f j) -> f i }
   deriving (Functor)
 
-lift :: Monad m => m a -> ContT m i i a
-lift = ContT . (>>=)
+lift :: Base.Monad m => m a -> ContT m i i a
+lift = ContT . (Base.>>=)
 
-evalContT :: Applicative p => ContT p a a a -> p a
+evalContT :: Base.Applicative p => ContT p a a a -> p a
 evalContT = flip runContT pure
 
 mapContT :: (f i -> f j) -> ContT f i k a -> ContT f j k a
@@ -25,33 +28,39 @@
 callCC :: ((a -> ContT f j k b) -> ContT f i j a) -> ContT f i j a
 callCC f = ContT $ \ k -> runContT (f $ ContT . pure . k) k
 
-resetT :: Monad m => ContT m a i i -> ContT m j j a
-resetT (ContT f) = ContT (f pure >>=)
+resetT :: Base.Monad m => ContT m a i i -> ContT m j j a
+resetT (ContT f) = ContT (f pure Base.>>=)
 
-shiftT :: Monad m => ((a -> m j) -> ContT m i k k) -> ContT m i j a
+shiftT :: Base.Monad m => ((a -> m j) -> ContT m i k k) -> ContT m i j a
 shiftT f = ContT (flip runContT pure . f)
 
-instance IxApplicative (ContT f) where
-    ipure = ContT . flip id
-    iap = iapIxMonad
+instance Apply (ContT f) where
+    (<*>) = apIxMonad
 
-instance IxMonad (ContT f) where
-    ijoin (ContT f) = ContT $ f . flip runContT
+instance Bind (ContT f) where
+    join (ContT f) = ContT $ f . flip runContT
 
-instance Applicative (ContT f k k) where
-    pure = ipure
-    (<*>) = iap
+instance Base.Applicative (ContT f k k) where
+    pure = ContT . flip id
+    (<*>) = (<*>)
 
 instance Alternative p => Alternative (ContT p k k) where
     empty = ContT $ pure empty
-    ContT f <|> ContT g = ContT $ liftA2 (<|>) f g
+    ContT f <|> ContT g = ContT $ Base.liftA2 (<|>) f g
 
-instance Monad (ContT f k k) where
-    (>>=) = flip ibind
+instance Base.Monad (ContT f k k) where
+    (>>=) = (>>=)
 
-instance Alternative p => MonadPlus (ContT p k k) where
+instance Alternative p => Base.MonadPlus (ContT p k k) where
     mzero = empty
     mplus = (<|>)
 
-instance MonadFail m => MonadFail (ContT m k k) where
-    fail = ContT . pure . fail 
+instance Base.MonadFail m => Base.MonadFail (ContT m k k) where
+    fail = ContT . pure . Base.fail
+
+liftLocal
+ :: (Base.Monad m, Base.Applicative p)
+ => m r -> (p r -> m i -> m j) -> p r -> ContT m i j a -> ContT m j i a
+liftLocal ask local f (ContT xm) = ContT $ \ k -> do
+    g <- pure <$> ask
+    local f (xm (local g . k))
diff --git a/Control/Monad/Indexed/Trans/State.hs b/Control/Monad/Indexed/Trans/State.hs
--- a/Control/Monad/Indexed/Trans/State.hs
+++ b/Control/Monad/Indexed/Trans/State.hs
@@ -1,13 +1,21 @@
+-- | The indexed state transformer: each @'StateT' _ i j@ term takes an input of type @i@ and gives an output of type @j@.
+
 module Control.Monad.Indexed.Trans.State where
 
-import Control.Applicative
-import Control.Monad ((>=>), MonadPlus (..))
-import Control.Monad.Fix (MonadFix (..))
+import Prelude hiding ((<*>), Monad (..))
+import Control.Applicative (Alternative (..))
+import qualified Control.Applicative as Base
+import qualified Control.Monad as Base
+import qualified Control.Monad.Fix as Base
+import Control.Monad.Indexed.Signatures
 import Data.Functor.Indexed
 
 newtype StateT f i j a = StateT { runStateT :: i -> f (a, j) }
   deriving (Functor)
 
+lift :: Functor f => f a -> StateT f k k a
+lift xm = StateT $ \ k -> flip (,) k <$> xm
+
 mapStateT :: (f (a, j) -> g (b, k)) -> StateT f i j a -> StateT g i k b
 mapStateT f (StateT x) = StateT (f . x)
 
@@ -15,7 +23,7 @@
 modify f = modifyF (pure . f)
 
 modifyF :: Functor f => (i -> f j) -> StateT f i j i
-modifyF = StateT . liftA2 fmap (,)
+modifyF = StateT . Base.liftA2 fmap (,)
 
 get :: Applicative p => StateT p k k k
 get = modifyF pure
@@ -23,27 +31,53 @@
 put :: Applicative p => j -> StateT p i j ()
 put = StateT . pure . pure . (,) ()
 
-instance Monad m => IxApplicative (StateT m) where
-    ipure a = StateT $ pure . (,) a
-    StateT fm `iap` StateT xm = StateT $ \ i -> [(f x, k) | (f, j) <- fm i, (x, k) <- xm j]
+instance Base.Monad m => Apply (StateT m) where
+    StateT fm <*> StateT xm = StateT $ \ i -> [(f x, k) | (f, j) <- fm i, (x, k) <- xm j]
 
-instance Monad m => IxMonad (StateT m) where
-    ijoin = StateT . (>=> uncurry runStateT) . runStateT
+instance Base.Monad m => Bind (StateT m) where
+    join = StateT . (Base.>=> uncurry runStateT) . runStateT
 
-instance Monad m => Applicative (StateT m k k) where
-    pure = ipure
-    (<*>) = iap
+instance Base.Monad m => Base.Applicative (StateT m k k) where
+    pure a = StateT $ pure . (,) a
+    (<*>) = (<*>)
 
-instance Monad m => Monad (StateT m k k) where
-    (>>=) = flip ibind
+instance Base.Monad m => Base.Monad (StateT m k k) where
+    (>>=) = (>>=)
 
-instance MonadPlus m => Alternative (StateT m k k) where
+instance Base.MonadPlus m => Alternative (StateT m k k) where
     empty = StateT (pure empty)
-    StateT a <|> StateT b = StateT (liftA2 (<|>) a b)
+    StateT a <|> StateT b = StateT (Base.liftA2 (<|>) a b)
 
-instance MonadPlus m => MonadPlus (StateT m k k) where
+instance Base.MonadPlus m => Base.MonadPlus (StateT m k k) where
     mzero = empty
     mplus = (<|>)
 
-instance MonadFix m => MonadFix (StateT m k k) where
-    mfix f = StateT $ mfix . \ k -> flip runStateT k . f . fst
+instance Base.MonadFix m => Base.MonadFix (StateT m k k) where
+    mfix f = StateT $ Base.mfix . \ k -> flip runStateT k . f . fst
+
+liftCallCC
+ :: CallCC f g h (a, i) (b, j) (c, k) (d, l)
+ -> CallCC (StateT f e j) (StateT g i k) (StateT h i l) a b c d
+liftCallCC callCC f =
+    StateT $ \ st ->
+    callCC $ \ k ->
+    runStateT (f $ \ a -> StateT $ \ _ -> k (a, st)) st
+
+liftCatch
+ :: Catch e f g h (a, i) (b, j) (c, k)
+ -> Catch e (StateT f l i) (StateT g l j) (StateT h l k) a b c
+liftCatch catchE (StateT xm) h = StateT $ \ st -> xm st `catchE` \ e -> runStateT (h e) st
+
+liftListen
+ :: Functor f
+ => Listen w f (a, j) b
+ -> Listen w (StateT f i j) a (i -> b)
+liftListen listen xm = StateT $ \ st ->
+    flip fmap (listen (xm st)) $ \ ~((a, st'), w) -> ((a, w), st')
+
+liftPass
+ :: Functor f
+ => Pass z f g (a, k) (b, j)
+ -> Pass z (StateT f i k) (StateT g i j) a b
+liftPass pass (StateT xm) = StateT $ \ st ->
+    pass $ flip fmap (xm st) $ \ ~((a, f), st') -> ((a, st'), f)
diff --git a/Control/Monad/Indexed/Trans/Writer.hs b/Control/Monad/Indexed/Trans/Writer.hs
new file mode 100644
--- /dev/null
+++ b/Control/Monad/Indexed/Trans/Writer.hs
@@ -0,0 +1,66 @@
+-- | The indexed writer transformer: each @'WriterT' κ f@ term bears a morphism of @κ@ atop its argument, which are composed as the 'WriterT' terms are 'join'ed and @('<*>')@d.
+
+module Control.Monad.Indexed.Trans.Writer where
+
+import Prelude hiding ((.), id, (<*>), Monad (..))
+import Control.Applicative (Alternative (..))
+import qualified Control.Applicative as Base
+import Control.Category (Category (id))
+import Control.Semigroupoid (Semigroupoid (..))
+import qualified Control.Monad as Base
+import qualified Control.Monad.Fix as Base
+import Control.Monad.Indexed.Signatures
+import Data.Functor.Indexed
+
+newtype WriterT κ f i j a = WriterT { runWriterT :: f (a, κ i j) }
+  deriving (Foldable, Functor, Traversable)
+
+lift :: (Functor f, Category κ) => f a -> WriterT κ f k k a
+lift xm = WriterT $ flip (,) id <$> xm
+
+mapWriterT :: (f (a, κ i j) -> f' (a', κ' i' j')) -> WriterT κ f i j a -> WriterT κ' f' i' j' a'
+mapWriterT f = WriterT . f . runWriterT
+
+tell :: Applicative p => κ i j -> WriterT κ p i j ()
+tell = WriterT . pure . (,) ()
+
+listen :: Functor f => WriterT κ f i j a -> WriterT κ f i j (a, κ i j)
+listen = mapWriterT . fmap $ \ (a, v) -> ((a, v), v)
+
+pass :: Functor f => WriterT κ f i j (a, κ i j -> κ i j) -> WriterT κ f i j a
+pass = mapWriterT . fmap $ \ ((a, f), v) -> (a, f v)
+
+censor :: Functor f => (κ i j -> κ' i' j') -> WriterT κ f i j a -> WriterT κ' f i' j' a
+censor = mapWriterT . fmap . fmap
+
+instance (Base.Applicative p, Category κ) => Base.Applicative (WriterT κ p k k) where
+    pure = lift . pure
+    (<*>) = (<*>)
+
+instance (Base.Monad m, Category κ) => Base.Monad (WriterT κ m k k) where
+    (>>=) = (>>=)
+
+instance (Semigroupoid κ, Base.Applicative p) => Apply (WriterT κ p) where
+    WriterT x <*> WriterT y = WriterT $ (\ (f, u) (a, v) -> (f a, v . u)) <$> x Base.<*> y
+
+instance (Semigroupoid κ, Base.Monad m) => Bind (WriterT κ m) where
+    join (WriterT x) = WriterT [(b, v . u) | (WriterT y, u) <- x, (b, v) <- y]
+
+instance (Alternative p, Category κ) => Alternative (WriterT κ p k k) where
+    empty = WriterT empty
+    WriterT x <|> WriterT y = WriterT (x <|> y)
+
+instance (Base.MonadPlus p, Category κ) => Base.MonadPlus (WriterT κ p k k)
+
+instance (Base.MonadFix m, Category κ) => Base.MonadFix (WriterT κ m k k) where
+    mfix f = WriterT $ Base.mfix (\ (a, u) -> (\ (b, v) -> (b, v . u)) <$> runWriterT (f a))
+
+liftCallCC
+ :: Category κ
+ => CallCC f g h (a, κ k k) (b, κ i₁ j₁) (c, κ i₂ j₂) (d, κ i₃ j₃) -> CallCC (WriterT κ f i₁ j₁) (WriterT κ g i₂ j₂) (WriterT κ h i₃ j₃) a b c d
+liftCallCC callCC f = WriterT $ callCC $ \ k -> runWriterT $ f $ \ a -> WriterT $ k (a, id)
+
+liftCatch
+ :: Catch e f g h (a, κ i₁ j₁) (b, κ i₂ j₂) (c, κ i₃ j₃)
+ -> Catch e (WriterT κ f i₁ j₁) (WriterT κ g i₂ j₂) (WriterT κ h i₃ j₃) a b c
+liftCatch catchE (WriterT xm) h = WriterT $ catchE xm $ runWriterT . h
diff --git a/Data/Functor/Indexed.hs b/Data/Functor/Indexed.hs
--- a/Data/Functor/Indexed.hs
+++ b/Data/Functor/Indexed.hs
@@ -1,47 +1,140 @@
 {-# LANGUAGE RebindableSyntax #-}
-{-# LANGUAGE MonadComprehensions #-}
 {-# LANGUAGE QuantifiedConstraints #-}
+{-# LANGUAGE DerivingVia #-}
 
-module Data.Functor.Indexed where
+-- | Indexed applicative functors and monads: see 'Apply', 'Bind', 'Cobind'.
 
-import Control.Applicative
+module Data.Functor.Indexed (module Data.Functor.Indexed, pure, copure) where
+
+import Prelude (Functor (fmap), pure, (<$>), Foldable, Traversable, Eq, Ord)
+import qualified Control.Applicative as Base
 import Control.Category
-import Control.Monad
-import Control.Comonad
+import qualified Control.Monad as Base
+import Control.Comonad (copure)
+import qualified Control.Comonad as Base
 import Data.Function (flip)
+import Data.Kind (Type)
 
-class (∀ i j . Functor (p i j)) => IxApplicative p where
-    ipure :: a -> p k k a
-    iap :: p i j (a -> b) -> p j k a -> p i k b
+infixl 4 <*>, *>, <*, <**>
+-- | Functors into which binary (and thus @n@-ary) functions can be lifted
+--
+-- Laws:
+--
+-- * @('.') '<$>' u '<*>' v '<*>' w = u '<*>' (v '<*>' w)@
+--
+-- Relations of methods:
+--
+-- * @'liftA2' f x y = f '<$>' x '<*>' y@
+-- * @('<*>') = 'liftA2' 'id'@
+-- * @('*>') = 'liftA2' ('pure' 'id')@
+-- * @('<*') = 'liftA2' ('id' 'pure')@
+class (∀ i j . Functor (p i j)) => Apply p where
+    {-# MINIMAL (<*>) | liftA2 #-}
 
-class IxApplicative m => IxMonad m where
-    ijoin :: m i j (m j k a) -> m i k a
-    ijoin = ibind id
+    (<*>) :: p i j (a -> b) -> p j k a -> p i k b
+    (<*>) = liftA2 id
 
-    ibind :: (a -> m j k b) -> m i j a -> m i k b
-    ibind f = ijoin . fmap f
+    (*>) :: p i j a -> p j k b -> p i k b
+    (*>) = liftA2 (pure id)
 
-iapIxMonad :: IxMonad m => m i j (a -> b) -> m j k a -> m i k b
-iapIxMonad fm xm = [f x | f <- fm, x <- xm] where
-    return = ipure
-    (>>=) = flip ibind
+    (<*) :: p i j a -> p j k b -> p i k a
+    (<*) = liftA2 pure
 
-class (∀ i j . Functor (ɯ i j)) => IxComonad ɯ where
-    icut :: ɯ i k a -> ɯ i j (ɯ j k a)
-    icut = icobind id
+    liftA2 :: (a -> b -> c) -> p i j a -> p j k b -> p i k c
+    liftA2 f x y = f <$> x <*> y
 
-    icobind :: (ɯ j k a -> b) -> ɯ i k a -> ɯ i j b
-    icobind f = fmap f . icut
+(<**>) :: Apply p => p i j a -> p j k (a -> b) -> p i k b
+(<**>) = liftA2 (flip id)
 
+infixl 1 >>=
+-- | Functors of which nested levels can be combined
+--
+-- Laws in terms of 'join':
+--
+-- * @'join' '.' 'fmap' 'join' = 'join' '.' 'join'@
+--
+-- Laws in terms of '>>=':
+--
+-- * @('>>=' f) '.' ('>>=' g) = ('>>=' ('>>=' f) '.' g)@
+--
+-- Relation of 'join' and '>>=':
+--
+-- * @'join' = ('>>=' 'id')@
+-- * @('>>=' f) = 'join' '.' 'fmap' 'f'@
+class Apply m => Bind m where
+    {-# MINIMAL join | (>>=) #-}
+
+    join :: m i j (m j k a) -> m i k a
+    join = (>>= id)
+
+    (>>=) :: m i j a -> (a -> m j k b) -> m i k b
+    x >>= f = join (f <$> x)
+
+apIxMonad :: (Bind m, ∀ k . Base.Applicative (m k k)) => m i j (a -> b) -> m j k a -> m i k b
+apIxMonad fm xm = [f x | f <- fm, x <- xm] where
+    return = Base.pure
+
+infixr 1 <<=
+-- | Dual of 'Bind'
+--
+-- Laws in terms of 'cut':
+--
+-- * @'cut' '.' 'cut' = 'fmap' 'cut' '.' 'cut'@
+--
+-- Laws in terms of '<<=':
+--
+-- * @(f '<<=') '.' (g '<<=') = (f '.' (g '<<=') '<<=')@
+--
+-- Relation of 'cut' and '<<=':
+--
+-- * @'cut' = ('id' '<<=')@
+-- * @(f '<<=') = 'fmap' f . 'cut'@
+class (∀ i j . Functor (ɯ i j)) => Cobind ɯ where
+    {-# MINIMAL cut | (<<=) #-}
+
+    cut :: ɯ i k a -> ɯ i j (ɯ j k a)
+    cut = (<<=) id
+
+    (<<=) :: (ɯ j k a -> b) -> ɯ i k a -> ɯ i j b
+    (<<=) f = fmap f . cut
+
+infixl 1 =>>
+(=>>) :: Cobind ɯ => ɯ i k a -> (ɯ j k a -> b) -> ɯ i j b
+(=>>) = flip (<<=)
+
+infixr 1 =>=, =<=
+
+(=>=) :: Cobind ɯ => (ɯ j k a -> b) -> (ɯ i j b -> c) -> ɯ i k a -> c
+f =>= g = g . (f <<=)
+
+(=<=) :: Cobind ɯ => (ɯ i j b -> c) -> (ɯ j k a -> b) -> ɯ i k a -> c
+(=<=) = flip (=>=)
+
 newtype IxWrap f i j a = IxWrap { unIxWrap :: f a }
   deriving (Functor)
 
-instance Applicative p => IxApplicative (IxWrap p) where
-    ipure = IxWrap . pure
-    IxWrap f `iap` IxWrap x = IxWrap (f <*> x)
+deriving via (p :: Type -> Type) instance Base.Applicative p => Base.Applicative (IxWrap p i j)
+deriving via (m :: Type -> Type) instance Base.Monad m => Base.Monad (IxWrap m i j)
+instance Base.Comonad ɯ => Base.Comonad (IxWrap ɯ i j) where
+    cut (IxWrap ɯ) = IxWrap (IxWrap <$> Base.cut ɯ)
+    copure (IxWrap ɯ) = copure ɯ
 
-instance Monad m => IxMonad (IxWrap m) where
-    ijoin = IxWrap . join . fmap unIxWrap . unIxWrap
+instance Base.Applicative p => Apply (IxWrap p) where
+    IxWrap f <*> IxWrap x = IxWrap (f Base.<*> x)
 
-instance Comonad ɯ => IxComonad (IxWrap ɯ) where
-    icut = IxWrap . fmap IxWrap . cut . unIxWrap
+instance Base.Monad m => Bind (IxWrap m) where
+    join = IxWrap . Base.join . fmap unIxWrap . unIxWrap
+
+instance Base.Comonad ɯ => Cobind (IxWrap ɯ) where
+    cut = IxWrap . fmap IxWrap . Base.cut . unIxWrap
+
+infixr 1 >=>, <=<, =<<
+
+(>=>) :: Bind m => (a -> m i j b) -> (b -> m j k c) -> a -> m i k c
+f >=> g = (>>= g) . f
+
+(<=<) :: Bind m => (b -> m j k c) -> (a -> m i j b) -> a -> m i k c
+(<=<) = flip (>=>)
+
+(=<<) :: Bind m => (a -> m j k b) -> m i j a -> m i k b
+(=<<) = flip (>>=)
diff --git a/Data/Functor/Indexed/Const.hs b/Data/Functor/Indexed/Const.hs
new file mode 100644
--- /dev/null
+++ b/Data/Functor/Indexed/Const.hs
@@ -0,0 +1,19 @@
+-- | The indexed constant functor: a @'Const' κ@ ignores its final argument and merely holds a morphism of @κ@, which are composed as the @'Const'@ terms are 'join'ed and @('<*>')@d.
+
+module Data.Functor.Indexed.Const (Const (..)) where
+
+import Prelude hiding (Applicative (..), (.), id)
+import qualified Control.Applicative as Base
+import Control.Category (Category (id))
+import Control.Semigroupoid
+import Data.Functor.Indexed
+
+newtype Const κ a b z = Const { getConst :: κ a b }
+  deriving (Eq, Ord, Show, Foldable, Functor, Traversable)
+
+instance Semigroupoid κ => Apply (Const κ) where
+    Const f <*> Const g = Const (g . f)
+
+instance Category κ => Base.Applicative (Const κ a a) where
+    pure = pure (Const id)
+    (<*>) = (<*>)
diff --git a/bench/Main.hs b/bench/Main.hs
deleted file mode 100644
--- a/bench/Main.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Main where
-
-import Criterion.Main
-
-main :: IO ()
-main = defaultMain []
diff --git a/hs-ix.cabal b/hs-ix.cabal
--- a/hs-ix.cabal
+++ b/hs-ix.cabal
@@ -1,7 +1,7 @@
 name:                hs-ix
-version:             0.1.1.0
-synopsis:            Indexed monads
--- description:
+version:             0.2.0.0
+synopsis:            Indexed applicative functors and monads
+description:         Indexed applicative functors and monads: see "Data.Functor.Indexed" to begin.
 license:             BSD3
 license-file:        LICENSE
 author:              M Farkas-Dyck
@@ -15,70 +15,15 @@
 library
   hs-source-dirs:      .
   exposed-modules:     Data.Functor.Indexed
+                     , Data.Functor.Indexed.Const
+                     , Control.Comonad.Indexed.Trans.Costate
+                     , Control.Comonad.Indexed.Trans.Cowriter
+                     , Control.Monad.Indexed.Signatures
                      , Control.Monad.Indexed.Trans.Cont
                      , Control.Monad.Indexed.Trans.State
+                     , Control.Monad.Indexed.Trans.Writer
   build-depends:       base >= 4.7 && < 5
-                     , base-unicode-symbols
-                     , hs-functors
-                     , util
-  default-language:    Haskell2010
-  default-extensions:  UnicodeSyntax
-                     , LambdaCase
-                     , EmptyCase
-                     , InstanceSigs
-                     , PartialTypeSignatures
-                     , PolyKinds
-                     , ConstraintKinds
-                     , FlexibleContexts
-                     , FlexibleInstances
-                     , MonadComprehensions
-                     , StandaloneDeriving
-                     , DeriveFunctor, DeriveFoldable, DeriveTraversable
-  ghc-options:         -Wall -Wcompat -Wredundant-constraints -Wno-name-shadowing
-                       -Wincomplete-record-updates -Wincomplete-uni-patterns
-                       -Werror=incomplete-patterns
-                       -Werror=incomplete-uni-patterns
-                       -Werror=incomplete-record-updates
-                       -Werror=missing-fields
-                       -Werror=missing-methods
-
-test-suite test
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      test
-  main-is:             Main.hs
-  build-depends:       base >=4.11 && <5
-                     , smallcheck >=1.1.4
-                     , tasty >=1.0
-                     , tasty-smallcheck >=0.8
-                     , hs-ix
-  default-language:    Haskell2010
-  default-extensions:  UnicodeSyntax
-                     , LambdaCase
-                     , EmptyCase
-                     , InstanceSigs
-                     , PartialTypeSignatures
-                     , PolyKinds
-                     , ConstraintKinds
-                     , FlexibleContexts
-                     , FlexibleInstances
-                     , MonadComprehensions
-                     , StandaloneDeriving
-                     , DeriveFunctor, DeriveFoldable, DeriveTraversable
-  ghc-options:         -Wall -Wcompat -Wredundant-constraints -Wno-name-shadowing
-                       -Wincomplete-record-updates -Wincomplete-uni-patterns
-                       -Werror=incomplete-patterns
-                       -Werror=incomplete-uni-patterns
-                       -Werror=incomplete-record-updates
-                       -Werror=missing-fields
-                       -Werror=missing-methods
-
-benchmark bench
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      bench
-  main-is:             Main.hs
-  build-depends:       base >=4.11 && <5
-                     , criterion >=1.4.1
-                     , hs-ix
+                     , hs-functors >= 0.1.7 && < 0.2
   default-language:    Haskell2010
   default-extensions:  UnicodeSyntax
                      , LambdaCase
diff --git a/test/Main.hs b/test/Main.hs
deleted file mode 100644
--- a/test/Main.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-module Main where
-
-import Test.SmallCheck
-import Test.Tasty
-import Test.Tasty.SmallCheck
-
-main :: IO ()
-main = defaultMain $ testGroup "" []
