diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,12 @@
 # Revision history for capability
 
+## 0.2.0.0 -- 2019-03-22
+
+* Make HasStream a superclass of HasWriter.
+  See [#64](https://github.com/tweag/capability/pull/64)
+* Bumped version bounds on generic-lens.
+  See [#67](https://github.com/tweag/capability/pull/67)
+
 ## 0.1.0.0 -- 2018-10-04
 
 * Initial release.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -90,11 +90,8 @@
 For more complex examples, see the [Examples section](#examples) and
 the [`examples` subtree](./examples).
 
-This package is not available on Hackage yet, as some of its
-dependencies have not been updated to GHC 8.6, yet.
-
-API documentation can be found in the artifacts tab of any successful
-build in the [CircleCI project][circleci].
+API documentation can be found on
+[Hackage](http://hackage.haskell.org/package/capability).
 
 [circleci]: https://circleci.com/gh/tweag/capabilities-via/tree/master
 [mtl]: http://hackage.haskell.org/package/mtl
diff --git a/capability.cabal b/capability.cabal
--- a/capability.cabal
+++ b/capability.cabal
@@ -1,5 +1,5 @@
 name: capability
-version: 0.1.0.0
+version: 0.2.0.0
 homepage: https://github.com/tweag/capability
 license: BSD3
 license-file: LICENSE
@@ -47,7 +47,7 @@
       base >= 4.12 && < 5.0
     , dlist >= 0.8 && < 0.9
     , exceptions >= 0.6 && < 0.11
-    , generic-lens >= 1.0 && < 1.1
+    , generic-lens >= 1.0 && < 1.2
     , lens >= 4.16 && < 5.0
     , monad-control >= 1.0 && < 1.1
     , monad-unlift >= 0.2 && < 0.3
diff --git a/examples/WordCount.hs b/examples/WordCount.hs
--- a/examples/WordCount.hs
+++ b/examples/WordCount.hs
@@ -14,7 +14,7 @@
 
 import Capability.Reader
 import Capability.State
-import Capability.Writer
+import Capability.Stream
 import Control.Lens (ifor_)
 import Data.Coerce (coerce)
 import Data.Map.Strict (Map)
@@ -56,21 +56,21 @@
 
 -- | Count the occurrence of a single letter.
 countLetter ::
-  HasWriter "letterCount" (Occurrences Char) m
+  HasStream "letterCount" (Occurrences Char) m
   => Char -> m ()
-countLetter letter = tell @"letterCount" (oneOccurrence letter)
+countLetter letter = yield @"letterCount" (oneOccurrence letter)
 
 -- | Count the occurrence of a single word.
 countWord ::
-  HasWriter "wordCount" (Occurrences Text) m
+  HasStream "wordCount" (Occurrences Text) m
   => Text -> m ()
-countWord word = tell @"wordCount" (oneOccurrence word)
+countWord word = yield @"wordCount" (oneOccurrence word)
 
 
 -- | Count the occurrence of a single word and all the letters in it.
 countWordAndLetters ::
-  ( HasWriter "letterCount" (Occurrences Char) m
-  , HasWriter "wordCount" (Occurrences Text) m )
+  ( HasStream "letterCount" (Occurrences Char) m
+  , HasStream "wordCount" (Occurrences Text) m )
   => Text -> m ()
 countWordAndLetters word = do
   countWord word
@@ -80,8 +80,8 @@
 -- | Count the occurrences of words and letters in a text,
 -- excluding white space.
 countWordsAndLettersInText ::
-  ( HasWriter "letterCount" (Occurrences Char) m
-  , HasWriter "wordCount" (Occurrences Text) m )
+  ( HasStream "letterCount" (Occurrences Char) m
+  , HasStream "wordCount" (Occurrences Text) m )
   => Text -> m ()
 countWordsAndLettersInText text =
   mapM_ countWordAndLetters (Text.words text)
@@ -98,14 +98,14 @@
 -- | Counter application monad.
 newtype Counter a = Counter { runCounter :: CounterCtx -> IO a }
   deriving (Functor, Applicative, Monad) via (ReaderT CounterCtx IO)
-  deriving (HasWriter "letterCount" (Occurrences Char)) via
-    (WriterLog  -- Generate HasWriter using HasState of Monoid
+  deriving (HasStream "letterCount" (Occurrences Char)) via
+    (StreamLog  -- Generate HasStream using HasState of Monoid
     (ReaderIORef  -- Generate HasState from HasReader of IORef
     (Field "letterCount" "ctx"  -- Focus on the field letterCount
     (MonadReader  -- Generate HasReader using mtl MonadReader
     (ReaderT CounterCtx IO)))))  -- Use mtl ReaderT newtype
-  deriving (HasWriter "wordCount" (Occurrences Text)) via
-    WriterLog (ReaderIORef
+  deriving (HasStream "wordCount" (Occurrences Text)) via
+    StreamLog (ReaderIORef
     (Field "wordCount" "ctx" (MonadReader (ReaderT CounterCtx IO))))
 
 
diff --git a/examples/Writer.hs b/examples/Writer.hs
--- a/examples/Writer.hs
+++ b/examples/Writer.hs
@@ -9,6 +9,7 @@
 module Writer where
 
 import Capability.State
+import Capability.Stream
 import Capability.Writer
 import Control.Monad.State.Strict (State, StateT (..), runState)
 import Data.Monoid (Sum (..))
@@ -20,9 +21,10 @@
 -- | Increase a counter using a writer monad.
 useWriter :: HasWriter "count" (Sum Int) m => m ()
 useWriter = do
-  tell @"count" 1
-  tell @"count" 2
-  tell @"count" 3
+  -- Add 3 and retrieve result
+  ((), count) <- listen @"count" (tell @"count" 3)
+  -- Duplicate
+  tell @"count" count
 
 
 -- | Mix writer and state monad operations on the same tag.
@@ -49,7 +51,7 @@
 -- via clause.
 newtype WriterM a = WriterM (State Int a)
   deriving (Functor, Applicative, Monad)
-  deriving (HasWriter "count" (Sum Int))
+  deriving (HasStream "count" (Sum Int), HasWriter "count" (Sum Int))
     via WriterLog (Coerce (Sum Int) (MonadState (State Int)))
 
 runWriterM :: WriterM a -> (a, Int)
@@ -63,7 +65,7 @@
 -- See caveat on 'mixWriterState'.
 newtype BadWriterM a = BadWriterM (State Int a)
   deriving (Functor, Applicative, Monad)
-  deriving (HasWriter "count" (Sum Int))
+  deriving (HasStream "count" (Sum Int), HasWriter "count" (Sum Int))
     via WriterLog (Coerce (Sum Int) (MonadState (State Int)))
   deriving (HasState "count" Int)
     via MonadState (State Int)
diff --git a/src/Capability/Stream.hs b/src/Capability/Stream.hs
--- a/src/Capability/Stream.hs
+++ b/src/Capability/Stream.hs
@@ -40,13 +40,13 @@
     -- * Strategies
   , StreamStack(..)
   , StreamDList(..)
+  , StreamLog(..)
     -- ** Modifiers
   , module Capability.Accessors
   ) where
 
 import Capability.Accessors
 import Capability.State
-import Capability.Writer
 import Control.Monad.IO.Class (MonadIO)
 import Control.Monad.Primitive (PrimMonad)
 import Control.Monad.Trans.Class (MonadTrans, lift)
@@ -86,15 +86,46 @@
 -- | Accumulate streamed values in forward order in a difference list.
 newtype StreamDList m (a :: *) = StreamDList (m a)
   deriving (Functor, Applicative, Monad, MonadIO, PrimMonad)
-instance HasWriter tag (DList a) m => HasStream tag a (StreamDList m) where
-  yield_ _ = coerce @(a -> m ()) $ tell @tag . DList.singleton
+-- | This instance may seem a bit odd at first. All it does is wrap each
+-- 'yield'ed value in a single element difference list. How does re-yielding
+-- something else constitute a strategy for implementing 'HasStream' in the
+-- first place? The answer is that difference lists form a monoid, which allows
+-- a second stragegy to be used which accumulates all 'yield's in a single
+-- value, actually eliminating the 'HasStream' constraint this time.
+--
+-- 'StreamLog' below in fact does this, so the easiest way to fully eliminate
+-- the 'HasStream' constraint as described above is:
+--
+-- > deriving (HasStream tag w) via
+-- >   StreamDList (StreamLog (MonadState SomeStateMonad))
+instance HasStream tag (DList a) m => HasStream tag a (StreamDList m) where
+  yield_ _ = coerce @(a -> m ()) $ yield @tag . DList.singleton
   {-# INLINE yield_ #-}
 
+-- | Accumulate streamed values with their own monoid.
+newtype StreamLog m (a :: *) = StreamLog (m a)
+  deriving (Functor, Applicative, Monad, MonadIO, PrimMonad)
+instance (Monoid w, HasState tag w m) => HasStream tag w (StreamLog m) where
+    yield_ _ w = coerce @(m ()) $ modify' @tag (<> w)
+    {-# INLINE yield_ #-}
+
 instance Monad m => HasStream tag a (S.Stream (Of a) m) where
   yield_ _ = S.yield
   {-# INLINE yield_ #-}
 
 -- | Lift one layer in a monad transformer stack.
+--
+-- Note, that if the 'HasStream' instance is based on 'HasState', then it is
+-- more efficient to apply 'Lift' to the underlying state capability. E.g.
+-- you should favour
+--
+-- > deriving (HasStream tag w) via
+-- >   StreamLog (Lift (SomeTrans (MonadState SomeStateMonad)))
+--
+-- over
+--
+-- > deriving (HasStream tag w) via
+-- >   Lift (SomeTrans (StreamLog (MonadState SomeStateMonad)))
 instance (HasStream tag a m, MonadTrans t, Monad (t m))
   => HasStream tag a (Lift (t m))
   where
diff --git a/src/Capability/Writer.hs b/src/Capability/Writer.hs
--- a/src/Capability/Writer.hs
+++ b/src/Capability/Writer.hs
@@ -46,15 +46,15 @@
   , listen
   , pass
     -- * Strategies
-  , WriterLog(..)
+  , WriterLog
+  , StreamLog (..)
     -- ** Modifiers
   , module Capability.Accessors
   ) where
 
 import Capability.Accessors
 import Capability.State
-import Control.Monad.IO.Class (MonadIO)
-import Control.Monad.Primitive (PrimMonad)
+import Capability.Stream
 import Data.Coerce (Coercible, coerce)
 import GHC.Exts (Proxy#, proxy#)
 
@@ -69,7 +69,22 @@
 -- prop> listen @t (m >>= k) = listen @t m >>= \(a, w1) -> listen @t (k a) >>= \(b, w2) -> pure (b, w1 `mappend` w2)
 -- prop> pass @t (tell @t w >> pure (a, f)) = tell @t (f w) >> pure a
 -- prop> writer @t (a, w) = tell @t w >> pure a
-class (Monoid w, Monad m)
+--
+-- = A note on the 'HasStream' super class.
+--
+-- 'HasStream' offers one 'yield' method with the same signature as 'tell'.
+-- Many people's intuition, however, wouldn't connect the two: 'yield'ing
+-- tosses the value down some black-box chute, while 'tell'ing grows and
+-- accumulation via the monoid. The connection is since the 'chute' is opaque,
+-- the tosser cannot rule out there being such an accumulation at the chutes
+-- other end.
+--
+-- Formally, we reach the same conclusion. 'HasStream' has no laws,
+-- indicating the user can make no assumptions beyond the signature of 'yield'.
+-- 'HasWriter', with 'tell' defined as 'yield', is thus always compatable
+-- regardless of whatever additional methods it provides and laws by which it
+-- abides.
+class (Monoid w, Monad m, HasStream tag w m)
   => HasWriter (tag :: k) (w :: *) (m :: * -> *) | tag m -> w
   where
     -- | For technical reasons, this method needs an extra proxy argument.
@@ -79,11 +94,6 @@
     writer_ :: Proxy# tag -> (a, w) -> m a
     -- | For technical reasons, this method needs an extra proxy argument.
     -- You only need it if you are defining new instances of 'HasReader'.
-    -- Otherwise, you will want to use 'tell'.
-    -- See 'tell' for more documentation.
-    tell_ :: Proxy# tag -> w -> m ()
-    -- | For technical reasons, this method needs an extra proxy argument.
-    -- You only need it if you are defining new instances of 'HasReader'.
     -- Otherwise, you will want to use 'listen'.
     -- See 'listen' for more documentation.
     listen_ :: Proxy# tag -> m a -> m (a, w)
@@ -106,7 +116,7 @@
 -- | @tell \@tag w@
 -- appends @w@ to the output of the writer capability @tag@.
 tell :: forall tag w m. HasWriter tag w m => w -> m ()
-tell = tell_ (proxy# @_ @tag)
+tell = yield_ (proxy# @_ @tag)
 {-# INLINE tell #-}
 
 -- | @listen \@tag m@
@@ -132,16 +142,13 @@
   , Monad m, HasWriter tag w (t2 (t1 m)) )
   => HasWriter tag w ((t2 :.: t1) m)
 
-newtype WriterLog m a = WriterLog (m a)
-  deriving (Functor, Applicative, Monad, MonadIO, PrimMonad)
+type WriterLog = StreamLog
 
 instance (Monoid w, HasState tag w m)
   => HasWriter tag w (WriterLog m)
   where
-    writer_ tag (a, w) = tell_ tag w >> pure a
+    writer_ tag (a, w) = yield_ tag w >> pure a
     {-# INLINE writer_ #-}
-    tell_ _ w = coerce @(m ()) $ modify' @tag (<> w)
-    {-# INLINE tell_ #-}
     listen_ :: forall a. Proxy# tag -> WriterLog m a -> WriterLog m (a, w)
     listen_ _ m = coerce @(m (a, w)) $ do
       w0 <- get @tag
diff --git a/src/Capability/Writer/Discouraged.hs b/src/Capability/Writer/Discouraged.hs
--- a/src/Capability/Writer/Discouraged.hs
+++ b/src/Capability/Writer/Discouraged.hs
@@ -43,8 +43,6 @@
     writer_ :: forall a. Proxy# tag -> (a, w) -> Lift (t m) a
     writer_ _ = coerce @((a, w) -> t m a) $ lift . writer @tag
     {-# INLINE writer_ #-}
-    tell_ _ = coerce @(w -> t m ()) $ lift . tell @tag
-    {-# INLINE tell_ #-}
     listen_ :: forall a. Proxy# tag -> Lift (t m) a -> Lift (t m) (a, w)
     listen_ _ = coerce @(t m a -> t m (a, w)) $ \m -> do
       u <- askUnlift
