diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,12 @@
 CHANGELOG
 
+0.8.3 -> 0.8.4
+  - Updated to constraints-0.10
+  - Updated for GHC 8.4
+    - Updated to base-4.11
+    - Updated to template-haskell-2.13
+    - `Semigroup` is now a superclass of `Monoid`
+
 0.8.2 -> 0.8.3
   - Added Data.Functor.Free.TH to other-modules
   
diff --git a/free-functors.cabal b/free-functors.cabal
--- a/free-functors.cabal
+++ b/free-functors.cabal
@@ -1,5 +1,5 @@
 name:                free-functors
-version:             0.8.3
+version:             0.8.4
 synopsis:            Free functors, adjoint to functors that forget class constraints.
 description:         A free functor is a left adjoint to a forgetful functor. It used to be the case
                      that the only category that was easy to work with in Haskell was Hask itself, so
@@ -47,12 +47,12 @@
     Haskell2010
 
   build-depends:
-    base >= 4.9 && < 4.11,
-    template-haskell >= 2.11 && < 2.13,
-    constraints == 0.9.*,
+    base == 4.11.*,
+    template-haskell == 2.13.*,
+    constraints == 0.10.*,
     transformers == 0.5.*,
     comonad == 5.*,
-    algebraic-classes >= 0.9 && < 1.0,
+    algebraic-classes == 0.9.*,
     contravariant == 1.4.*,
     bifunctors == 5.*,
     profunctors == 5.*
diff --git a/src/Data/Constraint/Class1.hs b/src/Data/Constraint/Class1.hs
--- a/src/Data/Constraint/Class1.hs
+++ b/src/Data/Constraint/Class1.hs
@@ -35,7 +35,6 @@
 import Data.Functor.Contravariant
 import Data.Functor.Contravariant.Divisible
 import Data.Profunctor
-import Data.Semigroup
 
 -- | Proof that @b@ is a superclass of @h@, i.e. @h x@ entails @b x@.
 scls1 :: forall b h x. SuperClass1 b h => h x :- b x
@@ -89,7 +88,10 @@
   superClasses = Sub Dict
   containsSelf = Sub Dict
 instance HasSuperClasses Semigroup
-instance HasSuperClasses Monoid
+instance HasSuperClasses Monoid where
+  type SuperClasses Monoid = Monoid ': SuperClasses Semigroup
+  superClasses = Sub Dict
+  containsSelf = Sub Dict
 
 instance HasSuperClasses Functor
 instance HasSuperClasses Applicative where
diff --git a/src/Data/Functor/Free.hs b/src/Data/Functor/Free.hs
--- a/src/Data/Functor/Free.hs
+++ b/src/Data/Functor/Free.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 {-# LANGUAGE
     ConstraintKinds
   , GADTs
@@ -56,73 +57,14 @@
 
   ) where
 
-import Control.Comonad
 import Data.Function
-import Data.Semigroup
 
-import Data.Constraint hiding (Class)
-import Data.Constraint.Forall
-import Data.Constraint.Class1
-
-import Data.Foldable (Foldable(..))
-import Data.Traversable
 import Data.Void
 
-import Data.Algebra
 import Language.Haskell.TH.Syntax
 
 import Data.Functor.Free.TH
 
-
--- | The free functor for class @c@.
---
---   @Free c a@ is basically an expression tree with operations from class @c@
---   and variables/placeholders of type @a@, created with `unit`.
---   Monadic bind allows you to replace each of these variables with another sub-expression.
-newtype Free c a = Free { runFree :: forall b. c b => (a -> b) -> b }
-
--- | `unit` allows you to create @`Free` c@ values, together with the operations from the class @c@.
-unit :: a -> Free c a
-unit a = Free $ \k -> k a
-
--- | `rightAdjunct` is the destructor of @`Free` c@ values.
-rightAdjunct :: c b => (a -> b) -> Free c a -> b
-rightAdjunct f g = runFree g f
-
-rightAdjunctF :: ForallF c f => (a -> f b) -> Free c a -> f b
-rightAdjunctF = h instF rightAdjunct
-  where
-    h :: ForallF c f
-      => (ForallF c f :- c (f b))
-      -> (c (f b) => (a -> f b) -> Free c a -> f b)
-      -> (a -> f b) -> Free c a -> f b
-    h (Sub Dict) f = f
-
-class ForallLifted c where
-  dictLifted :: Applicative f => Dict (c (LiftAFree c f a))
-
-rightAdjunctLifted :: (ForallLifted c, Applicative f) => (a -> LiftAFree c f b) -> Free c a -> LiftAFree c f b
-rightAdjunctLifted = h dictLifted rightAdjunct
-  where
-    h :: Dict (c (t f b))
-      -> (c (t f b) => (a -> t f b) -> Free c a -> t f b)
-      -> (a -> t f b) -> Free c a -> t f b
-    h Dict f = f
-
--- | @counit = rightAdjunct id@
-counit :: c a => Free c a -> a
-counit = rightAdjunct id
-
--- | @leftAdjunct f = f . unit@
-leftAdjunct :: (Free c a -> b) -> a -> b
-leftAdjunct f = f . unit
-
--- | @transform f as = as >>= f unit@
---
--- @transform f . transform g = transform (g . f)@
-transform :: (forall r. c r => (b -> r) -> a -> r) -> Free c a -> Free c b
-transform t (Free f) = Free (f . t)
-
 -- | @unfold f = coproduct (unfold f) unit . f@
 --
 -- `inL` and `inR` are useful here. For example, the following creates the list @[1..10]@ as a @Free Monoid@:
@@ -139,33 +81,7 @@
 convertClosed :: c r => Free c Void -> r
 convertClosed = rightAdjunct absurd
 
-instance Functor (Free c) where
-  fmap f = transform (. f)
 
-instance Applicative (Free c) where
-  pure = unit
-  fs <*> as = transform (\k f -> rightAdjunct (k . f) as) fs
-
-instance Monad (Free c) where
-  return = unit
-  as >>= f = transform (\k -> rightAdjunct k . f) as
-
-newtype Extract a = Extract { getExtract :: a }
-newtype Duplicate f a = Duplicate { getDuplicate :: f (f a) }
-instance (ForallF c Extract, ForallF c (Duplicate (Free c)))
-  => Comonad (Free c) where
-  extract = getExtract . rightAdjunctF Extract
-  duplicate = getDuplicate . rightAdjunctF (Duplicate . unit . unit)
-
-instance SuperClass1 (Class f) c => Algebra f (Free c a) where
-  algebra fa = Free $ \k -> h scls1 (fmap (rightAdjunct k) fa)
-    where
-      h :: c b => (c b :- Class f b) -> f b -> b
-      h (Sub Dict) = evaluate
-      
-
-
-
 -- | Products of @Monoid@s are @Monoid@s themselves. But coproducts of @Monoid@s are not.
 -- However, the free @Monoid@ applied to the coproduct /is/ a @Monoid@, and it is the coproduct in the category of @Monoid@s.
 -- This is also called the free product, and generalizes to any algebraic class.
@@ -186,41 +102,16 @@
 initial = rightAdjunct absurd
 
 
-
-newtype LiftAFree c f a = LiftAFree { getLiftAFree :: f (Free c a) }
-
-instance (Applicative f, SuperClass1 (Class s) c) => Algebra s (LiftAFree c f a) where
-  algebra = LiftAFree . fmap algebra . traverse getLiftAFree
-
-instance ForallLifted c => Foldable (Free c) where
-  foldMap = foldMapDefault
-
-instance ForallLifted c => Traversable (Free c) where
-  traverse f = getLiftAFree . rightAdjunctLifted (LiftAFree . fmap unit . f)
-
-
-data ShowHelper f a = ShowUnit a | ShowRec (f (ShowHelper f a))
-
-instance Algebra f (ShowHelper f a) where
-  algebra = ShowRec
-
-instance (Show a, Show (f (ShowHelper f a))) => Show (ShowHelper f a) where
-  showsPrec p (ShowUnit a) = showParen (p > 10) $ showString "unit " . showsPrec 11 a
-  showsPrec p (ShowRec f) = showsPrec p f
-
-instance (Show a, Show (Signature c (ShowHelper (Signature c) a)), c (ShowHelper (Signature c) a)) => Show (Free c a) where
-  showsPrec p = showsPrec p . rightAdjunct (ShowUnit :: a -> ShowHelper (Signature c) a)
-  
 -- | Derive the instances of @`Free` c a@ for the class @c@, `Show`, `Foldable` and `Traversable`.
 --
 -- For example:
 --
 -- @deriveInstances ''Num@
 deriveInstances :: Name -> Q [Dec]
-deriveInstances = deriveInstances' True ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper
+deriveInstances = deriveInstances' True
 
-deriveInstances' False ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper ''Num
-deriveInstances' False ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper ''Fractional
-deriveInstances' False ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper ''Floating
-deriveInstances' False ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper ''Semigroup
-deriveInstances' False ''ForallLifted 'dictLifted ''Free ''LiftAFree ''ShowHelper ''Monoid
+deriveInstances' False ''Num
+deriveInstances' False ''Fractional
+deriveInstances' False ''Floating
+deriveInstances' False ''Semigroup
+deriveInstances' False ''Monoid
diff --git a/src/Data/Functor/Free/TH.hs b/src/Data/Functor/Free/TH.hs
--- a/src/Data/Functor/Free/TH.hs
+++ b/src/Data/Functor/Free/TH.hs
@@ -18,12 +18,116 @@
 
 import Data.Constraint hiding (Class)
 import Data.Constraint.Class1
+import Data.Constraint.Forall
 
+import Control.Comonad
+import Data.Algebra
 import Data.Algebra.TH
 import Language.Haskell.TH.Syntax
+import Data.Traversable
 
-deriveInstances' :: Bool -> Name -> Name -> Name -> Name -> Name -> Name -> Q [Dec]
-deriveInstances' withHSC forallLiftedNm dictLiftedNm freeNm liftAFreeNm showHelperNm nm = getSignatureInfo nm >>= h where
+-- | The free functor for class @c@.
+--
+--   @Free c a@ is basically an expression tree with operations from class @c@
+--   and variables/placeholders of type @a@, created with `unit`.
+--   Monadic bind allows you to replace each of these variables with another sub-expression.
+newtype Free c a = Free { runFree :: forall b. c b => (a -> b) -> b }
+
+-- | `unit` allows you to create @`Free` c@ values, together with the operations from the class @c@.
+unit :: a -> Free c a
+unit a = Free $ \k -> k a
+
+-- | `rightAdjunct` is the destructor of @`Free` c@ values.
+rightAdjunct :: c b => (a -> b) -> Free c a -> b
+rightAdjunct f g = runFree g f
+
+rightAdjunctF :: ForallF c f => (a -> f b) -> Free c a -> f b
+rightAdjunctF = h instF rightAdjunct
+  where
+    h :: ForallF c f
+      => (ForallF c f :- c (f b))
+      -> (c (f b) => (a -> f b) -> Free c a -> f b)
+      -> (a -> f b) -> Free c a -> f b
+    h (Sub Dict) f = f
+
+-- | @counit = rightAdjunct id@
+counit :: c a => Free c a -> a
+counit = rightAdjunct id
+
+-- | @leftAdjunct f = f . unit@
+leftAdjunct :: (Free c a -> b) -> a -> b
+leftAdjunct f = f . unit
+
+-- | @transform f as = as >>= f unit@
+--
+-- @transform f . transform g = transform (g . f)@
+transform :: (forall r. c r => (b -> r) -> a -> r) -> Free c a -> Free c b
+transform t (Free f) = Free (f . t)
+
+
+instance Functor (Free c) where
+  fmap f = transform (. f)
+
+instance Applicative (Free c) where
+  pure = unit
+  fs <*> as = transform (\k f -> rightAdjunct (k . f) as) fs
+
+instance Monad (Free c) where
+  return = unit
+  as >>= f = transform (\k -> rightAdjunct k . f) as
+
+newtype Extract a = Extract { getExtract :: a }
+newtype Duplicate f a = Duplicate { getDuplicate :: f (f a) }
+instance (ForallF c Extract, ForallF c (Duplicate (Free c)))
+  => Comonad (Free c) where
+  extract = getExtract . rightAdjunctF Extract
+  duplicate = getDuplicate . rightAdjunctF (Duplicate . unit . unit)
+      
+
+class ForallLifted c where
+  dictLifted :: Applicative f => Dict (c (LiftAFree c f a))
+
+rightAdjunctLifted :: (ForallLifted c, Applicative f) => (a -> LiftAFree c f b) -> Free c a -> LiftAFree c f b
+rightAdjunctLifted = h dictLifted rightAdjunct
+  where
+    h :: Dict (c (t f b))
+      -> (c (t f b) => (a -> t f b) -> Free c a -> t f b)
+      -> (a -> t f b) -> Free c a -> t f b
+    h Dict f = f
+
+newtype LiftAFree c f a = LiftAFree { getLiftAFree :: f (Free c a) }
+
+instance SuperClass1 (Class f) c => Algebra f (Free c a) where
+  algebra fa = Free $ \k -> h scls1 (fmap (rightAdjunct k) fa)
+    where
+      h :: c b => (c b :- Class f b) -> f b -> b
+      h (Sub Dict) = evaluate
+      
+instance (Applicative f, SuperClass1 (Class s) c) => Algebra s (LiftAFree c f a) where
+  algebra = LiftAFree . fmap algebra . traverse getLiftAFree
+
+instance ForallLifted c => Foldable (Free c) where
+  foldMap = foldMapDefault
+
+instance ForallLifted c => Traversable (Free c) where
+  traverse f = getLiftAFree . rightAdjunctLifted (LiftAFree . fmap unit . f)
+
+
+data ShowHelper f a = ShowUnit a | ShowRec (f (ShowHelper f a))
+
+instance Algebra f (ShowHelper f a) where
+  algebra = ShowRec
+
+instance (Show a, Show (f (ShowHelper f a))) => Show (ShowHelper f a) where
+  showsPrec p (ShowUnit a) = showParen (p > 10) $ showString "unit " . showsPrec 11 a
+  showsPrec p (ShowRec f) = showsPrec p f
+
+instance (Show a, Show (Signature c (ShowHelper (Signature c) a)), c (ShowHelper (Signature c) a)) => Show (Free c a) where
+  showsPrec p = showsPrec p . rightAdjunct (ShowUnit :: a -> ShowHelper (Signature c) a)
+
+
+deriveInstances' :: Bool -> Name -> Q [Dec]
+deriveInstances' withHSC nm = getSignatureInfo nm >>= h where
   h sigInfo =
     concat <$> sequenceA
     [ deriveSignature nm
@@ -32,28 +136,17 @@
     , deriveInstanceWith_skipSignature showHelperHeader $ return []
     , deriveSuperclassInstances showHelperHeader
     , hasSuperClassesInstance
-    , return $ [InstanceD Nothing [] (AppT (ConT forallLiftedNm) c) [ValD (VarP dictLiftedNm) (NormalB (ConE 'Dict)) []]]
+    , [d|instance ForallLifted $c where dictLifted = Dict|]
     ]
     where
-      freeHeader = return $ ForallT [PlainTV a, PlainTV vc] [AppT (AppT superClass1 c) (VarT vc)]
-        (AppT c (AppT (AppT free (VarT vc)) (VarT a)))
-      liftAFreeHeader = return $ ForallT [PlainTV f, PlainTV a, PlainTV vc] [AppT (ConT ''Applicative) (VarT f), isSC]
-        (AppT c (AppT (AppT (AppT liftAFree (VarT vc)) (VarT f)) (VarT a)))
-      showHelperHeader = return $ ForallT [PlainTV a] []
-        (AppT c (AppT (AppT showHelper sig) (VarT a)))
-      hasSuperClassesInstance = if withHSC then [d|instance HasSuperClasses $(pure c) where {
-        type SuperClasses $(pure c) = $(pure c) ': $(scs);
+      freeHeader = [t|forall a vc. SuperClass1 $c vc => $c (Free vc a)|]
+      liftAFreeHeader = [t|forall f a vc. (Applicative f, SuperClass1 $c vc) => $c (LiftAFree vc f a)|]
+      showHelperHeader = [t|forall a. $c (ShowHelper $sig a)|]
+      hasSuperClassesInstance = if withHSC then [d|instance HasSuperClasses $c where {
+        type SuperClasses $c = $c ': $scs;
         superClasses = Sub Dict;
         containsSelf = Sub Dict
       }|] else return []
-      scs = foldr (\(SuperclassTH scnm _ _) q -> [t|SuperClasses $(pure (ConT scnm)) ++ $(q)|]) [t|'[]|] $ superclasses sigInfo
-      isSC = AppT (AppT superClass1 c) (VarT vc)
-      free = ConT freeNm
-      liftAFree = ConT liftAFreeNm
-      showHelper = ConT showHelperNm
-      superClass1 = ConT ''SuperClass1
-      c = ConT nm
-      sig = ConT $ signatureName sigInfo
-      a = mkName "a"
-      f = mkName "f"
-      vc = mkName "c"
+      scs = foldr (\(SuperclassTH scnm _ _) q -> [t|SuperClasses $(pure (ConT scnm)) ++ $q|]) [t|'[]|] $ superclasses sigInfo
+      c = pure $ ConT nm
+      sig = pure . ConT $ signatureName sigInfo
