diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.4.10 [2021.11.16]
+-------------------
+* Allow the test suite to build with recent GHCs.
+* Drop support for pre-8.0 versions of GHC.
+
 0.4.9 [2021.02.17]
 ------------------
 * Allow building with `lens-5.*`.
diff --git a/ersatz.cabal b/ersatz.cabal
--- a/ersatz.cabal
+++ b/ersatz.cabal
@@ -1,5 +1,5 @@
 name:           ersatz
-version:        0.4.9
+version:        0.4.10
 license:        BSD3
 license-file:   LICENSE
 author:         Edward A. Kmett, Eric Mertens, Johan Kiviniemi
@@ -75,13 +75,14 @@
 
 build-type:     Simple
 cabal-version:  >= 1.10
-tested-with:    GHC == 7.10.3
-              , GHC == 8.0.2
+tested-with:    GHC == 8.0.2
               , GHC == 8.2.2
               , GHC == 8.4.4
               , GHC == 8.6.5
-              , GHC == 8.8.3
-              , GHC == 8.10.1
+              , GHC == 8.8.4
+              , GHC == 8.10.7
+              , GHC == 9.0.1
+              , GHC == 9.2.1
 extra-source-files:
   .gitignore
   .hlint.yaml
@@ -161,29 +162,25 @@
 
 library
   ghc-options: -Wall
-  if impl(ghc >= 8.6)
-    ghc-options: -Wno-star-is-type
   hs-source-dirs: src
   default-language: Haskell2010
 
   build-depends:
     array                >= 0.2      && < 0.6,
-    base                 >= 4.8      && < 5,
+    base                 >= 4.9      && < 5,
     bytestring           >= 0.10.4.0 && < 0.12,
     containers           >= 0.2.0.1  && < 0.7,
     data-default         >= 0.5      && < 0.8,
-    lens                 >= 3.8      && < 6,
+    lens                 >= 4        && < 6,
     mtl                  >= 1.1      && < 2.3,
     process              >= 1.1      && < 1.7,
     semigroups           >= 0.16     && < 1,
+    streams              >= 3.3      && < 4,
     temporary            >= 1.1      && < 1.4,
     transformers         >= 0.3      && < 0.6,
     unordered-containers == 0.2.*,
     attoparsec
 
-  if impl(ghc >= 7.4 && < 7.6)
-    build-depends: ghc-prim
-
   exposed-modules:
     Ersatz
     Ersatz.Bit
@@ -223,8 +220,6 @@
       mtl,
       parsec >= 3.1 && < 3.2,
       semigroups
-    if impl(ghc >= 7.4 && < 7.6)
-      build-depends: ghc-prim
   else
     buildable: False
   main-is: Main.hs
@@ -244,8 +239,6 @@
       base < 5,
       ersatz,
       mtl
-    if impl(ghc >= 7.4 && < 7.6)
-      build-depends: ghc-prim
   else
     buildable: False
   default-language: Haskell2010
diff --git a/examples/regexp-grid/RegexpGrid/Problem.hs b/examples/regexp-grid/RegexpGrid/Problem.hs
--- a/examples/regexp-grid/RegexpGrid/Problem.hs
+++ b/examples/regexp-grid/RegexpGrid/Problem.hs
@@ -13,7 +13,7 @@
 import Control.Monad.Reader
 import Control.Monad.RWS.Strict hiding ((<>))
 import Control.Lens
-import Data.Foldable (asum)
+import qualified Data.Foldable as F (asum)
 import Data.Map (Map)
 import qualified Data.Map as Map
 #if !(MIN_VERSION_base(4,11,0))
@@ -162,7 +162,7 @@
 
 -- A choice of regexps. The 'Alternative' sum of all of them.
 reBit (Choice res next) = do
-  asum (map reBit res)
+  F.asum (map reBit res)
   reBit next
 
 -- Capture a group.
diff --git a/examples/regexp-grid/RegexpGrid/Regexp.hs b/examples/regexp-grid/RegexpGrid/Regexp.hs
--- a/examples/regexp-grid/RegexpGrid/Regexp.hs
+++ b/examples/regexp-grid/RegexpGrid/Regexp.hs
@@ -1,11 +1,7 @@
-{-# LANGUAGE CPP #-}
 -- | A parser for a subset of the regular expression syntax.
 
 module RegexpGrid.Regexp (Regexp (..), parseRegexp) where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative hiding ((<|>), many)
-#endif
 import Control.Monad
 import Data.Char
 import Text.Parsec
diff --git a/examples/regexp-grid/RegexpGrid/Types.hs b/examples/regexp-grid/RegexpGrid/Types.hs
--- a/examples/regexp-grid/RegexpGrid/Types.hs
+++ b/examples/regexp-grid/RegexpGrid/Types.hs
@@ -1,18 +1,12 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 
 module RegexpGrid.Types
 ( Pos (..)
 , Field (..)
 ) where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
 import Data.Char (chr, ord)
-import Data.Typeable
 import Ersatz
 import GHC.Generics
 
@@ -34,7 +28,7 @@
 -- 5 bits are enough for A–Z. (The subset of the alphabet used by the regexps
 -- also requires 5 bits. For simplicity, just use the full alphabet.)
 newtype Field = Field Bit5
-  deriving (Show, Typeable, Generic)
+  deriving (Show, Generic)
 
 instance Boolean   Field
 instance Variable  Field
diff --git a/examples/sudoku/Main.hs b/examples/sudoku/Main.hs
--- a/examples/sudoku/Main.hs
+++ b/examples/sudoku/Main.hs
@@ -1,15 +1,11 @@
-{-# LANGUAGE CPP #-}
 module Main (main) where
 
 import Prelude hiding ((&&), (||), not, and, or, all, any)
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
 import Control.Monad
 import Data.Array (Array, (!))
 import qualified Data.Array as Array
-import Data.List
+import qualified Data.List as List
 import Data.Word
 import Ersatz
 
@@ -51,7 +47,7 @@
     bottom  = bar "└" "───────" "┴" "┘"
 
     bar begin fill middle end =
-      begin ++ intercalate middle (replicate 3 fill) ++ end
+      begin ++ List.intercalate middle (replicate 3 fill) ++ end
 
 renderLine :: Array (Word8,Word8) Word8 -> Word8 -> String
 renderLine sol y = unwords . renderGroups "│" "│" "│"
@@ -62,6 +58,6 @@
 
 renderGroups :: a -> a -> a -> [a] -> [a]
 renderGroups begin middle end values =
-  [begin] ++ intercalate [middle] (chunks 3 values) ++ [end]
+  [begin] ++ List.intercalate [middle] (chunks 3 values) ++ [end]
   where
-    chunks n = unfoldr $ \xs -> splitAt n xs <$ guard (not (null xs))
+    chunks n = List.unfoldr $ \xs -> splitAt n xs <$ guard (not (null xs))
diff --git a/examples/sudoku/Sudoku/Cell.hs b/examples/sudoku/Sudoku/Cell.hs
--- a/examples/sudoku/Sudoku/Cell.hs
+++ b/examples/sudoku/Sudoku/Cell.hs
@@ -1,18 +1,16 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 
 module Sudoku.Cell (Cell(..)) where
 
 import Prelude hiding ((&&), (||), not, and, or, all, any)
 
-import Data.Typeable (Typeable)
 import Data.Word
 import Ersatz
 import GHC.Generics
 
 newtype Cell = Cell Bit4
-  deriving (Show, Typeable, Generic)
+  deriving (Show, Generic)
 
 instance Boolean   Cell
 instance Variable  Cell
diff --git a/examples/sudoku/Sudoku/Problem.hs b/examples/sudoku/Sudoku/Problem.hs
--- a/examples/sudoku/Sudoku/Problem.hs
+++ b/examples/sudoku/Sudoku/Problem.hs
@@ -1,12 +1,8 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 module Sudoku.Problem (problem, range) where
 
 import Prelude hiding ((&&), (||), not, and, or, all, any)
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
 import Control.Monad.Reader
 import Data.Array (Array, (!))
 import qualified Data.Array as Array
diff --git a/src/Ersatz/Bit.hs b/src/Ersatz/Bit.hs
--- a/src/Ersatz/Bit.hs
+++ b/src/Ersatz/Bit.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE DefaultSignatures #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE Trustworthy #-}
 {-# LANGUAGE Rank2Types #-}
@@ -29,16 +28,11 @@
 
 import Control.Applicative
 import Control.Monad.State
-#if __GLASGOW_HASKELL__ < 710
-import Data.Foldable (Foldable, toList)
-#else
 import Data.Foldable (toList)
-#endif
 import qualified Data.Foldable as Foldable
 import qualified Data.Traversable as Traversable
 import Data.Sequence (Seq, (<|), (|>), (><))
 import qualified Data.Sequence as Seq
-import Data.Typeable
 import Ersatz.Codec
 import Ersatz.Internal.Formula
 import Ersatz.Internal.Literal
@@ -64,7 +58,6 @@
   | Not !Bit
   | Var !Literal
   | Run ( forall m s . MonadSAT s m => m Bit )
-  deriving (Typeable)
 
 instance Show Bit where
   showsPrec d (And xs)  = showParen (d > 10) $
diff --git a/src/Ersatz/BitChar.hs b/src/Ersatz/BitChar.hs
--- a/src/Ersatz/BitChar.hs
+++ b/src/Ersatz/BitChar.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE TypeFamilies #-}
 --------------------------------------------------------------------
 -- |
@@ -14,7 +13,6 @@
 import Data.Char (chr,ord)
 import Control.Monad (replicateM)
 import Prelude hiding ((&&))
-import Data.Typeable (Typeable)
 
 import Ersatz.Bit
 import Ersatz.Bits
@@ -28,7 +26,7 @@
 
 -- | Encoding of the full range of 'Char' values.
 newtype BitChar = BitChar Bits
-  deriving (Show,Typeable)
+  deriving Show
 
 instance Codec BitChar where
   type Decoded BitChar = Char
diff --git a/src/Ersatz/Bits.hs b/src/Ersatz/Bits.hs
--- a/src/Ersatz/Bits.hs
+++ b/src/Ersatz/Bits.hs
@@ -1,7 +1,5 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2015, © Eric Mertens 2014, Johan Kiviniemi 2013
@@ -13,7 +11,7 @@
 -- 'Bits' is an arbitrary length natural number type
 --------------------------------------------------------------------
 module Ersatz.Bits
-  ( 
+  (
   -- * Fixed length bit vectors
     Bit1(..), Bit2(..), Bit3(..), Bit4(..), Bit5(..), Bit6(..), Bit7(..), Bit8(..)
   -- * Variable length bit vectors
@@ -31,16 +29,9 @@
 import Control.Monad.Trans.State (State, runState, get, put)
 import Data.Bits ((.&.), (.|.), shiftL, shiftR)
 import qualified Data.Bits as Data
-#if __GLASGOW_HASKELL__ < 710
-import Data.Foldable (Foldable, toList)
-#else
 import Data.Foldable (toList)
-#endif
 import Data.List (unfoldr, foldl')
-#if __GLASGOW_HASKELL__ < 710
-import Data.Traversable (traverse)
-#endif
-import Data.Typeable (Typeable)
+import Data.Stream.Infinite (Stream(..))
 import Data.Word (Word8)
 import Ersatz.Bit
 import Ersatz.Codec
@@ -51,21 +42,21 @@
 import Prelude hiding (and, or, not, (&&), (||))
 
 -- | A container of 1 'Bit' that 'encode's from and 'decode's to 'Word8'
-newtype Bit1 = Bit1 Bit deriving (Show,Typeable,Generic)
+newtype Bit1 = Bit1 Bit deriving (Show,Generic)
 -- | A container of 2 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit2 = Bit2 !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit2 = Bit2 !Bit !Bit deriving (Show,Generic)
 -- | A container of 3 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit3 = Bit3 !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit3 = Bit3 !Bit !Bit !Bit deriving (Show,Generic)
 -- | A container of 4 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit4 = Bit4 !Bit !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit4 = Bit4 !Bit !Bit !Bit !Bit deriving (Show,Generic)
 -- | A container of 5 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit5 = Bit5 !Bit !Bit !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit5 = Bit5 !Bit !Bit !Bit !Bit !Bit deriving (Show,Generic)
 -- | A container of 6 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit6 = Bit6 !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit6 = Bit6 !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Generic)
 -- | A container of 7 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit7 = Bit7 !Bit !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit7 = Bit7 !Bit !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Generic)
 -- | A container of 8 'Bit's that 'encode's from and 'decode's to 'Word8'
-data Bit8 = Bit8 !Bit !Bit !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Typeable,Generic)
+data Bit8 = Bit8 !Bit !Bit !Bit !Bit !Bit !Bit !Bit !Bit deriving (Show,Generic)
 
 instance Boolean Bit1
 instance Boolean Bit2
@@ -106,42 +97,42 @@
 instance Codec Bit1 where
   type Decoded Bit1 = Word8
   decode s (Bit1 a) = boolsToNum1 <$> decode s a
-  encode i = Bit1 a where (a:_) = bitsOf i
+  encode i = Bit1 a where (a:>_) = bitsOf i
 
 instance Codec Bit2 where
   type Decoded Bit2 = Word8
   decode s (Bit2 a b) = boolsToNum2 <$> decode s a <*> decode s b
-  encode i = Bit2 a b where (b:a:_) = bitsOf i
+  encode i = Bit2 a b where (b:>a:>_) = bitsOf i
 
 instance Codec Bit3 where
   type Decoded Bit3 = Word8
   decode s (Bit3 a b c) = boolsToNum3 <$> decode s a <*> decode s b <*> decode s c
-  encode i = Bit3 a b c where (c:b:a:_) = bitsOf i
+  encode i = Bit3 a b c where (c:>b:>a:>_) = bitsOf i
 
 instance Codec Bit4 where
   type Decoded Bit4 = Word8
   decode s (Bit4 a b c d) = boolsToNum4 <$> decode s a <*> decode s b <*> decode s c <*> decode s d
-  encode i = Bit4 a b c d where (d:c:b:a:_) = bitsOf i
+  encode i = Bit4 a b c d where (d:>c:>b:>a:>_) = bitsOf i
 
 instance Codec Bit5 where
   type Decoded Bit5 = Word8
   decode s (Bit5 a b c d e) = boolsToNum5 <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e
-  encode i = Bit5 a b c d e where (e:d:c:b:a:_) = bitsOf i
+  encode i = Bit5 a b c d e where (e:>d:>c:>b:>a:>_) = bitsOf i
 
 instance Codec Bit6 where
   type Decoded Bit6 = Word8
   decode s (Bit6 a b c d e f) = boolsToNum6 <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f
-  encode i = Bit6 a b c d e f where (f:e:d:c:b:a:_) = bitsOf i
+  encode i = Bit6 a b c d e f where (f:>e:>d:>c:>b:>a:>_) = bitsOf i
 
 instance Codec Bit7 where
   type Decoded Bit7 = Word8
   decode s (Bit7 a b c d e f g) = boolsToNum7 <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f <*> decode s g
-  encode i = Bit7 a b c d e f g where (g:f:e:d:c:b:a:_) = bitsOf i
+  encode i = Bit7 a b c d e f g where (g:>f:>e:>d:>c:>b:>a:>_) = bitsOf i
 
 instance Codec Bit8 where
   type Decoded Bit8 = Word8
   decode s (Bit8 a b c d e f g h) = boolsToNum8 <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f <*> decode s g <*> decode s h
-  encode i = Bit8 a b c d e f g h where (h:g:f:e:d:c:b:a:_) = bitsOf i
+  encode i = Bit8 a b c d e f g h where (h:>g:>f:>e:>d:>c:>b:>a:>_) = bitsOf i
 
 boolsToNum1 :: Bool -> Word8
 boolsToNum1 = boolToNum
@@ -167,8 +158,8 @@
 boolsToNum8 :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Word8
 boolsToNum8 a b c d e f g h = boolsToNum [a,b,c,d,e,f,g,h]
 
-bitsOf :: (Num a, Data.Bits a) => a -> [Bit]
-bitsOf n = bool (numToBool (n .&. 1)) : bitsOf (n `shiftR` 1)
+bitsOf :: (Num a, Data.Bits a) => a -> Stream Bit
+bitsOf n = bool (numToBool (n .&. 1)) :> bitsOf (n `shiftR` 1)
 {-# INLINE bitsOf #-}
 
 numToBool :: (Eq a, Num a) => a -> Bool
@@ -243,8 +234,7 @@
 -- suitable for comparisons and arithmetic. Bits are stored
 -- in little-endian order to enable phantom 'false' values
 -- to be truncated.
-newtype Bits = Bits { _getBits :: [Bit] } 
-  deriving Typeable
+newtype Bits = Bits { _getBits :: [Bit] }
 
 instance Show Bits where
   showsPrec d (Bits xs) = showParen (d > 10) $
@@ -349,7 +339,7 @@
 
 -- | Predicate for odd-valued 'Bits's.
 isOdd :: HasBits b => b -> Bit
-isOdd b = case unbits b of 
+isOdd b = case unbits b of
   []    -> false
   (x:_) -> x
 
diff --git a/src/Ersatz/Codec.hs b/src/Ersatz/Codec.hs
--- a/src/Ersatz/Codec.hs
+++ b/src/Ersatz/Codec.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeFamilies #-}
 --------------------------------------------------------------------
@@ -19,6 +18,7 @@
 import Data.Array
 import Data.HashMap.Lazy (HashMap)
 import Data.IntMap (IntMap)
+import Data.Kind
 import Data.Map (Map)
 import Data.Sequence (Seq)
 import Data.Traversable
@@ -29,13 +29,9 @@
 
 -- | This class describes data types that can be marshaled to or from a SAT solver.
 class Codec a where
-  type Decoded a :: *
+  type Decoded a :: Type
   -- | Return a value based on the solution if one can be determined.
-#if __GLASGOW_HASKELL__ < 710
-  decode :: (Alternative f, MonadPlus f) => Solution -> a -> f (Decoded a)
-#else
   decode :: MonadPlus f => Solution -> a -> f (Decoded a)
-#endif
   encode :: Decoded a -> a
 
 instance Codec Literal where
diff --git a/src/Ersatz/Internal/Formula.hs b/src/Ersatz/Internal/Formula.hs
--- a/src/Ersatz/Internal/Formula.hs
+++ b/src/Ersatz/Internal/Formula.hs
@@ -2,7 +2,6 @@
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
 {-# OPTIONS_HADDOCK not-home #-}
@@ -29,18 +28,12 @@
 import Data.IntSet (IntSet)
 import qualified Data.IntSet as IntSet
 import qualified Data.List as List (intersperse)
-import Data.Typeable
 import Ersatz.Internal.Literal
 
 import Data.Sequence (Seq)
 import qualified Data.Sequence as Seq
 import Data.Foldable (toList)
 
-#if !(MIN_VERSION_base(4,8,0))
-import Control.Applicative
-import Data.Monoid (Monoid(..))
-#endif
-
 #if !(MIN_VERSION_base(4,11,0))
 import Data.Semigroup (Semigroup(..))
 #endif
@@ -52,7 +45,7 @@
 -- | A disjunction of possibly negated atoms. Negated atoms are represented
 -- by negating the identifier.
 newtype Clause = Clause { clauseSet :: IntSet }
-  deriving (Eq, Ord, Typeable)
+  deriving (Eq, Ord)
 
 -- | Extract the (possibly negated) atoms referenced by a 'Clause'.
 clauseLiterals :: Clause -> [Literal]
@@ -76,7 +69,7 @@
 
 -- | A conjunction of clauses
 newtype Formula = Formula { formulaSet :: Seq Clause }
-  deriving (Eq, Ord, Typeable)
+  deriving (Eq, Ord)
 
 instance Semigroup Formula where
   Formula x <> Formula y = Formula (x <> y)
diff --git a/src/Ersatz/Internal/Literal.hs b/src/Ersatz/Internal/Literal.hs
--- a/src/Ersatz/Internal/Literal.hs
+++ b/src/Ersatz/Internal/Literal.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE DeriveDataTypeable #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2014, Johan Kiviniemi 2013
@@ -14,13 +13,11 @@
   , literalFalse, literalTrue
   ) where
 
-import Data.Typeable
-
 -- | A naked possibly-negated Atom, present in the target 'Ersatz.Solver.Solver'.
 --
 -- The literals @-1@ and @1@ are dedicated for the constant 'False' and the
 -- constant 'True' respectively.
-newtype Literal = Literal { literalId :: Int } deriving (Eq,Ord,Typeable)
+newtype Literal = Literal { literalId :: Int } deriving (Eq,Ord)
 
 instance Show Literal where
   showsPrec i = showsPrec i . literalId
diff --git a/src/Ersatz/Internal/Parser.hs b/src/Ersatz/Internal/Parser.hs
--- a/src/Ersatz/Internal/Parser.hs
+++ b/src/Ersatz/Internal/Parser.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2014, Johan Kiviniemi 2013
@@ -22,9 +21,6 @@
 import Control.Applicative
 import Control.Monad.State
 import Data.Char (isDigit)
-#if __GLASGOW_HASKELL__ < 710
-import Data.Traversable (traverse)
-#endif
 
 type Parser t a = StateT [t] [] a
 
diff --git a/src/Ersatz/Problem.hs b/src/Ersatz/Problem.hs
--- a/src/Ersatz/Problem.hs
+++ b/src/Ersatz/Problem.hs
@@ -4,15 +4,11 @@
 {-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE Trustworthy #-}
 {-# LANGUAGE ConstraintKinds #-}
 
 {-# OPTIONS_HADDOCK not-home #-}
-#ifndef MIN_VERSION_lens
-#define MIN_VERSION_lens(x,y,z) 1
-#endif
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2014, Johan Kiviniemi 2013
@@ -57,7 +53,6 @@
 import Data.IntSet (IntSet)
 import qualified Data.IntSet as IntSet
 import qualified Data.List as List
-import Data.Typeable
 import Ersatz.Internal.Formula
 import Ersatz.Internal.Literal
 import Ersatz.Internal.StableName
@@ -65,20 +60,10 @@
 import Data.Sequence (Seq)
 import qualified Data.Sequence as Seq
 
-#if !(MIN_VERSION_base(4,8,0))
-import Control.Applicative
-import Data.Foldable (foldMap)
-import Data.Monoid (Monoid(..))
-#endif
-
 #if !(MIN_VERSION_base(4,11,0))
 import Data.Semigroup (Semigroup(..))
 #endif
 
-#if !(MIN_VERSION_lens(4,0,0))
-import Control.Monad.Identity
-#endif
-
 -- | Constraint synonym for types that carry a SAT state.
 type MonadSAT  s m = (HasSAT  s, MonadState s m)
 
@@ -93,7 +78,7 @@
   { _lastAtom  :: {-# UNPACK #-} !Int      -- ^ The id of the last atom allocated
   , _formula   :: !Formula                 -- ^ a set of clauses to assert
   , _stableMap :: !(HashMap (StableName ()) Literal)  -- ^ a mapping used during 'Bit' expansion
-  } deriving Typeable
+  }
 
 class HasSAT s where
   sat :: Lens' s SAT
@@ -164,7 +149,7 @@
 data QSAT = QSAT
   { _universals :: !IntSet -- ^ a set indicating which literals are universally quantified
   , _qsatSat    :: SAT     -- ^ The rest of the information, in 'SAT'
-  } deriving (Show,Typeable)
+  } deriving Show
 
 class HasSAT t => HasQSAT t where
   qsat       :: Lens' t QSAT
@@ -308,7 +293,6 @@
 data Quant
   = Exists { getQuant :: {-# UNPACK #-} !Int }
   | Forall { getQuant :: {-# UNPACK #-} !Int }
-  deriving Typeable
 
 instance DIMACS SAT where
   dimacsComments _ = []
diff --git a/src/Ersatz/Solution.hs b/src/Ersatz/Solution.hs
--- a/src/Ersatz/Solution.hs
+++ b/src/Ersatz/Solution.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2014, Johan Kiviniemi 2013
@@ -15,15 +13,11 @@
   , Solver
   ) where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
 import Control.Lens
 import qualified Data.HashMap.Lazy as HashMap
 import Data.IntMap (IntMap)
 import qualified Data.IntMap.Strict as IntMap
 import Data.Ix
-import Data.Typeable
 import Ersatz.Internal.Literal
 import Ersatz.Problem
 import System.Mem.StableName (StableName)
@@ -31,7 +25,7 @@
 data Solution = Solution
   { solutionLiteral    :: Literal -> Maybe Bool
   , solutionStableName :: StableName () -> Maybe Bool
-  } deriving Typeable
+  }
 
 solutionFrom :: HasSAT s => IntMap Bool -> s -> Solution
 solutionFrom litMap qbf = Solution lookupLit lookupSN
diff --git a/src/Ersatz/Solver.hs b/src/Ersatz/Solver.hs
--- a/src/Ersatz/Solver.hs
+++ b/src/Ersatz/Solver.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 --------------------------------------------------------------------
 -- |
 -- Copyright :  © Edward Kmett 2010-2014, Johan Kiviniemi 2013
@@ -23,15 +22,9 @@
 import Ersatz.Solver.DepQBF
 import Ersatz.Solver.Minisat
 
-#if __GLASGOW_HASKELL__ < 710
 solveWith ::
-  (Monad m, Alternative n, MonadPlus n, HasSAT s, Default s, Codec a) =>
-  Solver s m -> StateT s m a -> m (Result, n (Decoded a))
-#else
-solveWith ::
   (Monad m, MonadPlus n, HasSAT s, Default s, Codec a) =>
   Solver s m -> StateT s m a -> m (Result, n (Decoded a))
-#endif
 solveWith solver m = do
   (a, problem) <- runStateT m def
   (res, litMap) <- solver problem
diff --git a/src/Ersatz/Solver/Minisat.hs b/src/Ersatz/Solver/Minisat.hs
--- a/src/Ersatz/Solver/Minisat.hs
+++ b/src/Ersatz/Solver/Minisat.hs
@@ -71,8 +71,9 @@
 parseSolution s =
   case B.words s of
     x : ys | x == "SAT" ->
-          foldl' ( \ m y -> let Just (v,_) = B.readInt y
-                            in  if 0 == v then m else IntMap.insert (abs v) (v>0) m
+          foldl' ( \ m y -> case B.readInt y of
+                              Just (v,_) -> if 0 == v then m else IntMap.insert (abs v) (v>0) m
+                              Nothing    -> error $ "parseSolution: Expected an Int, received " ++ show y
                  ) IntMap.empty ys
     _ -> IntMap.empty -- WRONG (should be Nothing)
 
