diff --git a/Control/Comonad.hs b/Control/Comonad.hs
--- a/Control/Comonad.hs
+++ b/Control/Comonad.hs
@@ -2,7 +2,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Comonad
--- Copyright   :  (C) 2008-2011 Edward Kmett,
+-- Copyright   :  (C) 2008-2012 Edward Kmett,
 --                (C) 2004 Dave Menendez
 -- License     :  BSD-style (see the file LICENSE)
 --
@@ -11,93 +11,254 @@
 -- Portability :  portable
 --
 ----------------------------------------------------------------------------
-module Control.Comonad ( 
-  -- * Extendable Functors
-    Extend(..)
+module Control.Comonad (
+  -- * Comonads
+    Comonad(..)
+  , liftW     -- :: Comonad w => (a -> b) -> w a -> w b
+  , wfix      -- :: Comonad w => w (w a -> a) -> a
+  , cfix      -- :: Comonad w => (w a -> a) -> w a
   , (=>=)
   , (=<=)
   , (<<=)
   , (=>>)
-  -- * Comonads
-  -- $definition
-  , Comonad(..)
-  , liftW     -- :: Comonad w => (a -> b) -> w a -> w b
-  , wfix      -- :: Comonad w => w (w a -> a) -> a
-
+  -- * Combining Comonads
+  , ComonadApply(..)
+  , (<@@>)    -- :: ComonadApply w => w a -> w (a -> b) -> w b
+  , liftW2    -- :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c
+  , liftW3    -- :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d
   -- * Cokleisli Arrows
   , Cokleisli(..)
+  -- * Functors
+  , Functor(..)
+  , (<$>)     -- :: Functor f => (a -> b) -> f a -> f b
+  , ($>)      -- :: Functor f => f a -> b -> f b
   ) where
 
-import Prelude hiding (id, (.))
+-- import _everything_
 import Control.Applicative
 import Control.Arrow
 import Control.Category
+import Control.Monad (ap)
+import Control.Monad.Instances
 import Control.Monad.Trans.Identity
 import Data.Functor.Identity
-import Data.Functor.Extend
-import Data.List.NonEmpty
-import Data.Typeable
-import Data.Semigroup
+import Data.List.NonEmpty hiding (map)
+import Data.Semigroup hiding (Product)
 import Data.Tree
+import Prelude hiding (id, (.))
+import Control.Monad.Fix
+import Data.Typeable
 
-{- | $definition -}
+infixl 4 <@, @>, <@@>, <@>, $>
+infixl 1 =>>
+infixr 1 <<=, =<=, =>=
 
-class Extend w => Comonad w where
-  -- | 
+{- |
+
+There are two ways to define a comonad:
+
+I. Provide definitions for 'extract' and 'extend'
+satisfying these laws:
+
+> extend extract      = id
+> extract . extend f  = f
+> extend f . extend g = extend (f . extend g)
+
+In this case, you may simply set 'fmap' = 'liftW'.
+
+These laws are directly analogous to the laws for monads
+and perhaps can be made clearer by viewing them as laws stating
+that Cokleisli composition must be associative, and has extract for
+a unit:
+
+> f =>= extract   = f
+> extract =>= f   = f
+> (f =>= g) =>= h = f =>= (g =>= h)
+
+II. Alternately, you may choose to provide definitions for 'fmap',
+'extract', and 'duplicate' satisfying these laws:
+
+> extract . duplicate      = id
+> fmap extract . duplicate = id
+> duplicate . duplicate    = fmap duplicate . duplicate
+
+In this case you may not rely on the ability to define 'fmap' in
+terms of 'liftW'.
+
+You may of course, choose to define both 'duplicate' /and/ 'extend'.
+In that case you must also satisfy these laws:
+
+> extend f  = fmap f . duplicate
+> duplicate = extend id
+> fmap f    = extend (f . extract)
+
+These are the default definitions of 'extend' and 'duplicate' and
+the definition of 'liftW' respectively.
+
+-}
+
+class Functor w => Comonad w where
+  -- |
   -- > extract . fmap f = f . extract
-  extract   :: w a -> a
+  extract :: w a -> a
 
--- | A suitable default definition for 'fmap' for a 'Comonad'. 
--- Promotes a function to a comonad.
---
--- > fmap f    = extend (f . extract)
-liftW :: Comonad w => (a -> b) -> w a -> w b
-liftW f = extend (f . extract)
-{-# INLINE liftW #-}
+  -- |
+  -- > duplicate = extend id
+  -- > fmap (fmap f) . duplicate = duplicate . fmap f
+  duplicate :: w a -> w (w a)
+  duplicate = extend id
 
--- | Comonadic fixed point
-wfix :: Comonad w => w (w a -> a) -> a
-wfix w = extract w (extend wfix w)
+  -- |
+  -- > extend f = fmap f . duplicate
+  extend :: (w a -> b) -> w a -> w b
+  extend f = fmap f . duplicate
 
--- * Comonads for Prelude types:
---
--- Instances: While Control.Comonad.Instances would be more symmetric
--- to the definition of Control.Monad.Instances in base, the reason
--- the latter exists is because of Haskell 98 specifying the types
--- @'Either' a@, @((,)m)@ and @((->)e)@ and the class Monad without
--- having the foresight to require or allow instances between them.
--- Here Haskell 98 says nothing about Comonads, so we can include the
--- instances directly avoiding the wart of orphan instances.
 
 instance Comonad ((,)e) where
+  duplicate p = (fst p, p)
   extract = snd
 
-instance (Semigroup m, Monoid m) => Comonad ((->)m) where
+instance Monoid m => Comonad ((->)m) where
+  duplicate f m = f . mappend m
   extract f = f mempty
 
--- * Comonads for types from 'transformers'.
---
--- This isn't really a transformer, so i have no compunction about including the instance here.
---
--- TODO: Petition to move Data.Functor.Identity into base
 instance Comonad Identity where
+  duplicate = Identity
   extract = runIdentity
 
--- Provided to avoid an orphan instance. Not proposed to standardize. 
--- If Comonad moved to base, consider moving instance into transformers?
 instance Comonad w => Comonad (IdentityT w) where
+  extend f (IdentityT m) = IdentityT (extend (f . IdentityT) m)
   extract = extract . runIdentityT
 
 instance Comonad Tree where
+  duplicate w@(Node _ as) = Node w (map duplicate as)
   extract (Node a _) = a
 
+instance Comonad NonEmpty where
+  extend f w@ ~(_ :| aas) = f w :| case aas of
+      []     -> []
+      (a:as) -> toList (extend f (a :| as))
+  extract ~(a :| _) = a
+
+-- | A @ComonadApply w@ is a strong lax symmetric semi-monoidal comonad on the
+-- category @Hask@ of Haskell types.
+--
+-- That it to say that @w@ is a strong lax symmetric semi-monoidal functor on
+-- Hask, where both extract and duplicate are symmetric monoidal natural
+-- transformations.
+--
+-- Laws:
+--
+-- > (.) <$> u <@> v <@> w = u <@> (v <@> w)
+-- > extract p (extract q) = extract (p <@> q)
+-- > duplicate (p <*> q) = (\r s -> fmap (r <@> s)) <@> duplicate q <*> duplicate q
+--
+-- If our type is both a ComonadApply and Applicative we further require
+--
+-- > (<*>) = (<@>)
+--
+-- Finally, if you choose to define ('\<\@') and (\'@\>@), the results of your
+-- definitions should match the following laws:
+--
+-- > a @> b = const id <$> a <@> b
+-- > a <@ b = const <$> a <@> b
+
+class Comonad w => ComonadApply w where
+  (<@>) :: w (a -> b) -> w a -> w b
+
+  (@>) :: w a -> w b -> w b
+  a @> b = const id <$> a <@> b
+
+  (<@) :: w a -> w b -> w a
+  a <@ b = const <$> a <@> b
+
+instance Semigroup m => ComonadApply ((,)m) where
+  (m, f) <@> (n, a) = (m <> n, f a)
+  (m, a) <@  (n, _) = (m <> n, a)
+  (m, _)  @> (n, b) = (m <> n, b)
+
+instance ComonadApply NonEmpty where
+  (<@>) = ap
+
+instance Monoid m => ComonadApply ((->)m) where
+  (<@>) = (<*>)
+  (<@ ) = (<* )
+  ( @>) = ( *>)
+
+instance ComonadApply Identity where
+  (<@>) = (<*>)
+  (<@ ) = (<* )
+  ( @>) = ( *>)
+
+instance ComonadApply w => ComonadApply (IdentityT w) where
+  IdentityT wa <@> IdentityT wb = IdentityT (wa <@> wb)
+
+instance ComonadApply Tree where
+  (<@>) = (<*>)
+  (<@ ) = (<* )
+  ( @>) = ( *>)
+
+-- | A suitable default definition for 'fmap' for a 'Comonad'.
+-- Promotes a function to a comonad.
+--
+-- > fmap f = liftW f = extend (f . extract)
+liftW :: Comonad w => (a -> b) -> w a -> w b
+liftW f = extend (f . extract)
+{-# INLINE liftW #-}
+
+-- | Comonadic fixed point à la Menendez
+wfix :: Comonad w => w (w a -> a) -> a
+wfix w = extract w (extend wfix w)
+
+-- | Comonadic fixed point à la Orchard
+cfix :: Comonad w => (w a -> a) -> w a
+cfix f = fix (extend f)
+{-# INLINE cfix #-}
+
+-- | 'extend' with the arguments swapped. Dual to '>>=' for a 'Monad'.
+(=>>) :: Comonad w => w a -> (w a -> b) -> w b
+(=>>) = flip extend
+{-# INLINE (=>>) #-}
+
+-- | 'extend' in operator form
+(<<=) :: Comonad w => (w a -> b) -> w a -> w b
+(<<=) = extend
+{-# INLINE (<<=) #-}
+
+-- | Right-to-left Cokleisli composition
+(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c
+f =<= g = f . extend g
+{-# INLINE (=<=) #-}
+
+-- | Left-to-right Cokleisli composition
+(=>=) :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c
+f =>= g = g . extend f
+{-# INLINE (=>=) #-}
+
+-- | A variant of '<@>' with the arguments reversed.
+(<@@>) :: ComonadApply w => w a -> w (a -> b) -> w b
+(<@@>) = liftW2 (flip id)
+{-# INLINE (<@@>) #-}
+
+-- | Lift a binary function into a comonad with zipping
+liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c
+liftW2 f a b = f <$> a <@> b
+{-# INLINE liftW2 #-}
+
+-- | Lift a ternary function into a comonad with zipping
+liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d
+liftW3 f a b c = f <$> a <@> b <@> c
+{-# INLINE liftW3 #-}
+
 -- | The 'Cokleisli' 'Arrow's of a given 'Comonad'
 newtype Cokleisli w a b = Cokleisli { runCokleisli :: w a -> b }
 
+#ifdef __GLASGOW_HASKELL__
 instance Typeable1 w => Typeable2 (Cokleisli w) where
   typeOf2 twab = mkTyConApp cokleisliTyCon [typeOf1 (wa twab)]
         where wa :: Cokleisli w a b -> w a
               wa = undefined
+#endif
 
 cokleisliTyCon :: TyCon
 #if MIN_VERSION_base(4,4,0)
@@ -124,7 +285,9 @@
 instance Comonad w => ArrowChoice (Cokleisli w) where
   left = leftApp
 
--- Cokleisli arrows are actually just a special case of a reader monad:
+instance ComonadApply w => ArrowLoop (Cokleisli w) where
+  loop (Cokleisli f) = Cokleisli (fst . wfix . extend f') where
+    f' wa wb = f ((,) <$> wa <@> (snd <$> wb))
 
 instance Functor (Cokleisli w a) where
   fmap f (Cokleisli g) = Cokleisli (f . g)
@@ -137,50 +300,6 @@
   return = Cokleisli . const
   Cokleisli k >>= f = Cokleisli $ \w -> runCokleisli (f (k w)) w
 
-instance Comonad NonEmpty where
-  extract ~(a :| _) = a
-
-
-{- $definition
-
-There are two ways to define a comonad:
-
-I. Provide definitions for 'extract' and 'extend'
-satisfying these laws:
-
-> extend extract      = id
-> extract . extend f  = f
-> extend f . extend g = extend (f . extend g)
-
-In this case, you may simply set 'fmap' = 'liftW'.
-
-These laws are directly analogous to the laws for monads
-and perhaps can be made clearer by viewing them as laws stating
-that Cokleisli composition must be associative, and has extract for
-a unit:
-
-> f =>= extract   = f
-> extract =>= f   = f
-> (f =>= g) =>= h = f =>= (g =>= h)
-
-II. Alternately, you may choose to provide definitions for 'fmap',
-'extract', and 'duplicate' satisfying these laws:
-
-> extract . duplicate      = id
-> fmap extract . duplicate = id
-> duplicate . duplicate    = fmap duplicate . duplicate
-
-In this case you may not rely on the ability to define 'fmap' in 
-terms of 'liftW'.
-
-You may of course, choose to define both 'duplicate' /and/ 'extend'. 
-In that case you must also satisfy these laws:
-
-> extend f  = fmap f . duplicate
-> duplicate = extend id
-> fmap f    = extend (f . extract)
-
-These are the default definitions of 'extend' and'duplicate' and 
-the definition of 'liftW' respectively.
-
--}
+-- | Replace the contents of a functor uniformly with a constant value.
+($>) :: Functor f => f a -> b -> f b
+($>) = flip (<$)
diff --git a/Data/Functor/Extend.hs b/Data/Functor/Extend.hs
deleted file mode 100644
--- a/Data/Functor/Extend.hs
+++ /dev/null
@@ -1,150 +0,0 @@
-{-# LANGUAGE CPP #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Functor.Extend
--- Copyright   :  (C) 2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
-----------------------------------------------------------------------------
-module Data.Functor.Extend
-  ( -- * $definition
-    Extend(..)
-  , (=>>)     -- :: Extend w => w a -> (w a -> b) -> w b
-  , (<<=)     -- :: Extend w => (w a -> b) -> w a -> w b
-  , (=>=)     -- :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c
-  , (=<=)     -- :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c
-  ) where
-
-import Prelude hiding (id, (.))
-import Control.Category
-import Control.Monad.Trans.Identity
-import Data.Functor.Identity
-import Data.Semigroup
-import Data.List (tails)
-import Data.List.NonEmpty (NonEmpty(..), toList)
-import Data.Sequence (Seq) 
-import qualified Data.Sequence as Seq
-import Data.Tree
-
-infixl 1 =>> 
-infixr 1 <<=, =<=, =>= 
-
-class Functor w => Extend w where
-  -- | 
-  -- > duplicate = extend id
-  -- > fmap (fmap f) . duplicate = duplicate . fmap f
-  duplicate :: w a -> w (w a)
-  -- |
-  -- > extend f  = fmap f . duplicate
-  extend    :: (w a -> b) -> w a -> w b
-
-  extend f = fmap f . duplicate
-  duplicate = extend id
-
--- | 'extend' with the arguments swapped. Dual to '>>=' for a 'Monad'.
-(=>>) :: Extend w => w a -> (w a -> b) -> w b
-(=>>) = flip extend
-{-# INLINE (=>>) #-}
-
--- | 'extend' in operator form 
-(<<=) :: Extend w => (w a -> b) -> w a -> w b
-(<<=) = extend
-{-# INLINE (<<=) #-}
-
--- | Right-to-left Cokleisli composition 
-(=<=) :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c
-f =<= g = f . extend g
-{-# INLINE (=<=) #-}
-
--- | Left-to-right Cokleisli composition
-(=>=) :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c
-f =>= g = g . extend f 
-{-# INLINE (=>=) #-}
-
--- * Extends for Prelude types:
---
--- Instances: While Data.Functor.Extend.Instances would be symmetric
--- to the definition of Control.Monad.Instances in base, the reason
--- the latter exists is because of Haskell 98 specifying the types
--- @'Either' a@, @((,)m)@ and @((->)e)@ and the class Monad without
--- having the foresight to require or allow instances between them.
---
--- Here Haskell 98 says nothing about Extend, so we can include the
--- instances directly avoiding the wart of orphan instances.
-
-instance Extend [] where
-  duplicate = tails
-
-instance Extend Maybe where
-  duplicate Nothing = Nothing
-  duplicate j = Just j
-
-instance Extend (Either a) where
-  duplicate (Left a) = Left a
-  duplicate r = Right r
-
-instance Extend ((,)e) where
-  duplicate p = (fst p, p)
-
-instance Semigroup m => Extend ((->)m) where
-  duplicate f m = f . (<>) m
-
-instance Extend Seq where
-  duplicate = Seq.tails
-
-instance Extend Tree where
-  duplicate w@(Node _ as) = Node w (map duplicate as)
-
--- I can't fix the world
--- instance (Monoid m, Extend n) => Extend (ReaderT m n) 
---   duplicate f m = f . mappend m
-
--- * Extends for types from 'transformers'.
---
--- This isn't really a transformer, so i have no compunction about including the instance here.
---
--- TODO: Petition to move Data.Functor.Identity into base
-instance Extend Identity where
-  duplicate = Identity
-
--- Provided to avoid an orphan instance. Not proposed to standardize. 
--- If Extend moved to base, consider moving instance into transformers?
-instance Extend w => Extend (IdentityT w) where
-  extend f (IdentityT m) = IdentityT (extend (f . IdentityT) m)
-
-instance Extend NonEmpty where
-  extend f w@ ~(_ :| aas) = f w :| case aas of
-      []     -> []
-      (a:as) -> toList (extend f (a :| as))
-
-{- $definition
-
-There are two ways to define an 'Extend' instance:
-
-I. Provide definitions for 'extend'
-satisfying this law:
-
-> extend f . extend g = extend (f . extend g)
-
-II. Alternately, you may choose to provide definitions for 'duplicate' 
-satisfying this laws:
-
-> duplicate . duplicate    = fmap duplicate . duplicate
-
-These are both equivalent to the statement that (=>=) is associative
-
-> (f =>= g) =>= h = f =>= (g =>= h)
-
-You may of course, choose to define both 'duplicate' /and/ 'extend'. 
-In that case you must also satisfy these laws:
-
-> extend f  = fmap f . duplicate
-> duplicate = extend id
-
-These are the default definitions of 'extend' and 'duplicate'.
-
--}
diff --git a/comonad.cabal b/comonad.cabal
--- a/comonad.cabal
+++ b/comonad.cabal
@@ -1,6 +1,6 @@
 name:          comonad
 category:      Control, Comonads
-version:       1.1.1.6
+version:       3.0
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -27,10 +27,9 @@
     base         >= 4       && < 5,
     transformers >= 0.2     && < 0.4,
     containers   >= 0.3     && < 0.6,
-    semigroups   >= 0.8.3.1 && < 0.9
+    semigroups   >= 0.8.3   && < 0.8.4
 
   exposed-modules:
     Control.Comonad
-    Data.Functor.Extend
 
   ghc-options: -Wall
