diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.9.2
+
+* MonoComonad
+
 ## 0.9.1
 
 * Fill in missing Mono\* instances [#72](https://github.com/snoyberg/mono-traversable/pull/72)
diff --git a/mono-traversable.cabal b/mono-traversable.cabal
--- a/mono-traversable.cabal
+++ b/mono-traversable.cabal
@@ -1,5 +1,5 @@
 name:                mono-traversable
-version:             0.9.1
+version:             0.9.2
 synopsis:            Type classes for mapping, folding, and traversing monomorphic containers
 description:         Monomorphic variants of the Functor, Foldable, and Traversable typeclasses. If you understand Haskell's basic typeclasses, you understand mono-traversable. In addition to what you are used to, it adds on an IsSequence typeclass and has code for marking data structures as non-empty.
 homepage:            https://github.com/snoyberg/mono-traversable
@@ -22,7 +22,7 @@
                        Data.MinLen
                        Data.ByteVector
   other-modules:       Data.GrowingAppend
-  build-depends:       base >= 4 && < 5
+  build-depends:       base >= 4.5 && < 5
                      , containers >= 0.4
                      , unordered-containers >=0.2
                      , hashable
diff --git a/src/Data/MinLen.hs b/src/Data/MinLen.hs
--- a/src/Data/MinLen.hs
+++ b/src/Data/MinLen.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 module Data.MinLen
     ( -- * Type level naturals
       -- ** Peano numbers
@@ -40,7 +41,7 @@
     , minimumBy
     ) where
 
-import Prelude (Num (..), Maybe (..), Int, Ordering (..), Eq, Ord, Read, Show, Functor (..), ($), flip)
+import Prelude (Num (..), Maybe (..), Int, Ordering (..), Eq, Ord (..), Read, Show, Functor (..), ($), flip, const, Bool (..), otherwise)
 import Data.Data (Data)
 import Data.Typeable (Typeable)
 import Control.Category
@@ -50,6 +51,7 @@
 import Data.Semigroup (Semigroup (..))
 import Data.GrowingAppend
 import Control.Monad (liftM)
+import Control.Monad.Trans.State.Strict (evalState, state)
 
 -- $peanoNumbers
 -- <https://wiki.haskell.org/Peano_numbers Peano numbers> are a simple way to
@@ -480,3 +482,32 @@
           -> Element mono
 minimumBy cmp = minimumByEx cmp . unMinLen
 {-# INLINE minimumBy #-}
+
+-- | 'oextract' is 'head'.
+--
+-- For @'oextend' f@, the new 'mono' is populated by applying @f@ to
+-- successive 'tail's of the original 'mono'.
+--
+-- For example, for @'MinLen' ('Succ' 'Zero') ['Int']@, or
+-- @'NonNull' ['Int']@:
+--
+-- @
+-- 'oextend' f [1,2,3,4,5] = [ f [1, 2, 3, 4, 5]
+--                           , f [2, 3, 4, 5]
+--                           , f [3, 4, 5]
+--                           , f [4, 5]
+--                           , f [5]
+--                           ]
+-- @
+--
+-- Meant to be a direct analogy to the instance for 'NonEmpty' @a@.
+--
+instance IsSequence mono
+    => MonoComonad (MinLen (Succ Zero) mono) where
+        oextract  = head
+        oextend f (MinLen mono) = MinLen
+                                . flip evalState mono
+                                . ofor mono
+                                . const
+                                . state
+                                $ \mono' -> (f (MinLen mono'), tailEx mono')
diff --git a/src/Data/MonoTraversable.hs b/src/Data/MonoTraversable.hs
--- a/src/Data/MonoTraversable.hs
+++ b/src/Data/MonoTraversable.hs
@@ -1,8 +1,9 @@
-{-# LANGUAGE DefaultSignatures    #-}
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeFamilies         #-}
-{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ConstrainedClassMethods #-}
+{-# LANGUAGE DefaultSignatures       #-}
+{-# LANGUAGE FlexibleContexts        #-}
+{-# LANGUAGE FlexibleInstances       #-}
+{-# LANGUAGE TypeFamilies            #-}
+{-# LANGUAGE UndecidableInstances    #-}
 -- | Type classes mirroring standard typeclasses, but working with monomorphic containers.
 --
 -- The motivation is that some commonly used data types (i.e., 'ByteString' and
@@ -63,7 +64,11 @@
 import Control.Monad.Trans.List (ListT)
 import Control.Monad.Trans.Identity (IdentityT)
 import Data.Functor.Apply (MaybeApply (..), WrappedApplicative)
-import Control.Comonad (Cokleisli)
+import Control.Comonad (Cokleisli, Comonad, extract, extend)
+import Control.Comonad.Store (StoreT)
+import Control.Comonad.Env (EnvT)
+import Control.Comonad.Traced (TracedT)
+import Data.Functor.Coproduct (Coproduct)
 import Control.Monad.Trans.Writer (WriterT)
 import qualified Control.Monad.Trans.Writer.Strict as Strict (WriterT)
 import Control.Monad.Trans.State (StateT(..))
@@ -85,7 +90,7 @@
 import qualified Data.Vector.Unboxed as U
 import qualified Data.Vector.Storable as VS
 import qualified Data.IntSet as IntSet
-import Data.Semigroup (Semigroup, Option (..))
+import Data.Semigroup (Semigroup, Option (..), Arg)
 import qualified Data.ByteString.Unsafe as SU
 import Data.DList (DList)
 import qualified Data.DList as DL
@@ -142,6 +147,11 @@
 type instance Element (Static f a b) = b
 type instance Element (U.Vector a) = a
 type instance Element (VS.Vector a) = a
+type instance Element (Arg a b) = b
+type instance Element (EnvT e w a) = a
+type instance Element (StoreT s w a) = a
+type instance Element (TracedT m w a) = a
+type instance Element (Coproduct f g a) = a
 
 -- | Monomorphic containers that can be mapped over.
 class MonoFunctor mono where
@@ -184,6 +194,11 @@
 instance MonoFunctor (Map k v)
 instance MonoFunctor (HashMap k v)
 instance MonoFunctor (Vector a)
+instance MonoFunctor (Arg a b)
+instance Functor w => MonoFunctor (EnvT e w a)
+instance Functor w => MonoFunctor (StoreT s w a)
+instance Functor w => MonoFunctor (TracedT m w a)
+instance (Functor f, Functor g) => MonoFunctor (Coproduct f g a)
 instance Arrow a => MonoFunctor (WrappedArrow a b c)
 instance Functor f => MonoFunctor (MaybeApply f a)
 instance Functor f => MonoFunctor (WrappedApplicative f a)
@@ -265,7 +280,10 @@
 
     -- | Compare the length of a monomorphic container and a given number.
     ocompareLength :: Integral i => mono -> i -> Ordering
-    ocompareLength c0 i0 = olength c0 `compare` fromIntegral i0 -- FIXME more efficient implementation
+    -- Basic implementation using length for most instance. See the list
+    -- instance below for support for infinite structures. Arguably, that
+    -- should be the default instead of this.
+    ocompareLength c0 i0 = olength c0 `compare` fromIntegral i0
     {-# INLINE ocompareLength #-}
 
     -- | Map each element of a monomorphic container to an action,
@@ -542,6 +560,11 @@
 instance MonoFoldable [a] where
     otoList = id
     {-# INLINE otoList #-}
+
+    ocompareLength [] i = 0 `compare` i
+    ocompareLength (_:xs) i
+        | i Prelude.<= 0 = GT
+        | otherwise = ocompareLength xs (i - 1)
 instance MonoFoldable (Maybe a) where
     omapM_ _ Nothing = return ()
     omapM_ f (Just x) = f x
@@ -1205,3 +1228,74 @@
 instance MonoPointed (Tree a) where
     opoint a = Node a []
     {-# INLINE opoint #-}
+
+
+-- | Typeclass for monomorphic containers where it is always okay to
+-- "extract" a value from with 'oextract', and where you can extrapolate
+-- any "extracting" function to be a function on the whole part with
+-- 'oextend'.
+--
+-- 'oextend' and 'oextract' should work together following the laws:
+--
+-- @
+-- 'oextend' 'oextract'      = 'id'
+-- 'oextract' . 'oextend' f  = f
+-- 'oextend' f . 'oextend' g = 'oextend' (f . 'oextend' g)
+-- @
+--
+-- As an intuition, @'oextend' f@ uses @f@ to "build up" a new @mono@ with
+-- pieces from the old one received by @f@.
+--
+class MonoFunctor mono => MonoComonad mono where
+    -- | Extract an element from @mono@.  Can be thought of as a dual
+    -- concept to @opoint@.
+    oextract :: mono -> Element mono
+    -- | "Extend" a @mono -> 'Element' mono@ function to be a @mono ->
+    -- mono@; that is, builds a new @mono@ from the old one by using pieces
+    -- glimpsed from the given function.
+    oextend :: (mono -> Element mono) -> mono -> mono
+
+    default oextract :: (Comonad w, (w a) ~ mono, Element (w a) ~ a)
+                   => mono -> Element mono
+    oextract = extract
+    {-# INLINE oextract #-}
+    default oextend :: (Comonad w, (w a) ~ mono, Element (w a) ~ a)
+                   => (mono -> Element mono) -> mono -> mono
+    oextend = extend
+    {-# INLINE oextend #-}
+
+-- Comonad
+instance MonoComonad (Tree a)
+instance MonoComonad (NonEmpty a)
+instance MonoComonad (Identity a)
+instance Monoid m => MonoComonad (m -> a)
+instance MonoComonad (e, a)
+instance MonoComonad (Arg a b)
+instance Comonad w => MonoComonad (IdentityT w a)
+instance Comonad w => MonoComonad (EnvT e w a)
+instance Comonad w => MonoComonad (StoreT s w a)
+instance (Comonad w, Monoid m) => MonoComonad (TracedT m w a)
+instance (Comonad f, Comonad g) => MonoComonad (Coproduct f g a)
+
+-- Not Comonad
+instance MonoComonad (ViewL a) where
+    oextract ~(x :< _) = x
+    {-# INLINE oextract #-}
+    oextend f w@ ~(_ :< xxs) =
+        f w :< case Seq.viewl xxs of
+                 EmptyL -> Seq.empty
+                 xs     -> case oextend f xs of
+                             EmptyL  -> Seq.empty
+                             y :< ys -> y Seq.<| ys
+
+instance MonoComonad (ViewR a) where
+    oextract ~(_ :> x) = x
+    {-# INLINE oextract #-}
+    oextend f w@ ~(xxs :> _) =
+        (case Seq.viewr xxs of
+           EmptyR -> Seq.empty
+           xs     -> case oextend f xs of
+                       EmptyR  -> Seq.empty
+                       ys :> y -> ys Seq.|> y
+        ) :> f w
+
diff --git a/src/Data/Sequences.hs b/src/Data/Sequences.hs
--- a/src/Data/Sequences.hs
+++ b/src/Data/Sequences.hs
@@ -1531,7 +1531,7 @@
 
 -- | Same as @sortBy . comparing@.
 --
--- Sicne 0.7.0
+-- Since 0.7.0
 sortOn :: (Ord o, SemiSequence seq) => (Element seq -> o) -> seq -> seq
 sortOn = sortBy . comparing
 {-# INLINE sortOn #-}
