diff --git a/descriptive.cabal b/descriptive.cabal
--- a/descriptive.cabal
+++ b/descriptive.cabal
@@ -1,5 +1,5 @@
 name:                descriptive
-version:             0.9.4
+version:             0.9.5
 synopsis:            Self-describing consumers/parsers; forms, cmd-line args, JSON, etc.
 description:         Self-describing consumers/parsers. See the README.md for more information. It is currently EXPERIMENTAL.
 stability:           Experimental
@@ -33,6 +33,8 @@
                    , text
                    , transformers
                    , vector
+  if impl(ghc < 8.0.1)
+    build-depends: semigroups
 
 test-suite test
     type: exitcode-stdio-1.0
diff --git a/src/Descriptive.hs b/src/Descriptive.hs
--- a/src/Descriptive.hs
+++ b/src/Descriptive.hs
@@ -6,6 +6,7 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE CPP #-}
 
 -- | Descriptive parsers.
 
@@ -30,7 +31,9 @@
 import Control.Monad.Identity
 import Control.Monad.State.Strict
 import Data.Bifunctor
-import Data.Monoid
+#if __GLASGOW_HASKELL__ < 804
+import Data.Semigroup
+#endif
 
 --------------------------------------------------------------------------------
 -- Running
@@ -74,11 +77,14 @@
   | None
   deriving (Show,Eq,Functor)
 
+instance Semigroup (Description d) where
+  (<>) None x = x
+  (<>) x None = x
+  (<>) x y = And x y
+
 instance Monoid (Description d) where
   mempty = None
-  mappend None x = x
-  mappend x None = x
-  mappend x y = And x y
+  mappend = (<>)
 
 -- | The bounds of a many-consumable thing.
 data Bound
@@ -229,9 +235,8 @@
               [])
   where redescribe = Bounded minb UnlimitedBound
 
-instance (Monoid a) => Monoid (Result (Description d) a) where
-  mempty = Succeeded mempty
-  mappend x y =
+instance (Semigroup a) => Semigroup (Result (Description d) a) where
+  x <> y =
     case x of
       Failed e -> Failed e
       Continued e ->
@@ -245,11 +250,18 @@
           Continued e -> Continued e
           Succeeded b -> Succeeded (a <> b)
 
-instance (Monoid a, Monad m) => Monoid (Consumer s d m a) where
+instance (Semigroup a, Monoid a) => Monoid (Result (Description d) a) where
+  mempty = Succeeded mempty
+  mappend = (<>)
+
+instance (Semigroup a, Monad m) => Semigroup (Consumer s d m a) where
+  (<>) = liftA2 (<>)
+
+instance (Semigroup a, Monoid a, Monad m) => Monoid (Consumer s d m a) where
   mempty =
     consumer (return mempty)
              (return mempty)
-  mappend = liftA2 (<>)
+  mappend = (<>)
 
 --------------------------------------------------------------------------------
 -- Combinators
diff --git a/src/Descriptive/Char.hs b/src/Descriptive/Char.hs
--- a/src/Descriptive/Char.hs
+++ b/src/Descriptive/Char.hs
@@ -1,12 +1,15 @@
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE CPP #-}
 
 -- | Consuming form a list of characters.
 
 module Descriptive.Char where
 
+#if __GLASGOW_HASKELL__ < 802
 import           Data.Traversable
+#endif
 import           Descriptive
 
 import           Control.Monad.State.Strict
diff --git a/src/Descriptive/Options.hs b/src/Descriptive/Options.hs
--- a/src/Descriptive/Options.hs
+++ b/src/Descriptive/Options.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE CPP #-}
 
 -- | Command-line options parser.
 
@@ -29,7 +30,9 @@
 import           Control.Monad.State.Strict
 import           Data.Char
 import           Data.List
+#if __GLASGOW_HASKELL__ < 804
 import           Data.Monoid
+#endif
 import           Data.Text (Text)
 import qualified Data.Text as T
 
