diff --git a/base-compat.cabal b/base-compat.cabal
--- a/base-compat.cabal
+++ b/base-compat.cabal
@@ -1,5 +1,5 @@
 name:             base-compat
-version:          0.6.0
+version:          0.7.0
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2012-2015 Simon Hengel,
@@ -22,6 +22,7 @@
       -Wall
   build-depends:
       base == 4.*
+    , ghc-prim
     , setenv
   extensions:
       CPP
@@ -35,14 +36,28 @@
   exposed-modules:
       Prelude.Compat
       Control.Applicative.Compat
+      Control.Concurrent.MVar.Compat
       Control.Exception.Compat
       Control.Monad.Compat
+      Data.Bits.Compat
       Data.Bool.Compat
       Data.Either.Compat
       Data.Foldable.Compat
+      Data.Function.Compat
       Data.Functor.Compat
+      Data.List.Compat
       Data.Monoid.Compat
+      Data.Ord.Compat
       Data.Traversable.Compat
+      Data.Version.Compat
+      Debug.Trace.Compat
+      Foreign.Compat
+      Foreign.Marshal.Compat
+      Foreign.Marshal.Alloc.Compat
+      Foreign.Marshal.Array.Compat
+      Foreign.Storable.Compat
+      GHC.Generics.Compat
+      System.Console.GetOpt.Compat
       System.Environment.Compat
       System.Exit.Compat
       Text.Read.Compat
diff --git a/src/Control/Applicative/Compat.hs b/src/Control/Applicative/Compat.hs
--- a/src/Control/Applicative/Compat.hs
+++ b/src/Control/Applicative/Compat.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE StandaloneDeriving #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Control.Applicative.Compat (
   module Base
@@ -6,10 +7,13 @@
 ) where
 import Control.Applicative as Base
 
+#if !MIN_VERSION_base(4,8,0)
+import Data.Traversable.Compat ()
+import GHC.Generics.Compat ()
+import Prelude.Compat
+#endif
+
 #if !MIN_VERSION_base(4,7,0)
-import Data.Monoid (Monoid(..),mempty,mappend)
-import Control.Monad (Monad(..))
-import Data.Function ((.))
 -- Added in base-4.7.0.0
 instance Monoid a => Monoid (Const a b) where
     mempty = Const mempty
@@ -19,4 +23,22 @@
 instance Monad m => Monad (WrappedMonad m) where
     return = WrapMonad . return
     a >>= f = WrapMonad (unwrapMonad a >>= unwrapMonad . f)
+
+deriving instance Eq a => Eq (ZipList a)
+deriving instance Ord a => Ord (ZipList a)
+deriving instance Read a => Read (ZipList a)
+deriving instance Show a => Show (ZipList a)
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
+deriving instance Eq a => Eq (Const a b)
+deriving instance Ord a => Ord (Const a b)
+
+instance Read a => Read (Const a b) where
+    readsPrec d = readParen (d > 10)
+        $ \r -> [(Const x,t) | ("Const", s) <- lex r, (x, t) <- readsPrec 11 s]
+
+instance Show a => Show (Const a b) where
+    showsPrec d (Const x) = showParen (d > 10) $
+                            showString "Const " . showsPrec 11 x
 #endif
diff --git a/src/Control/Concurrent/MVar/Compat.hs b/src/Control/Concurrent/MVar/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/MVar/Compat.hs
@@ -0,0 +1,27 @@
+module Control.Concurrent.MVar.Compat (
+  module Base
+, withMVarMasked
+) where
+import Control.Concurrent.MVar as Base
+
+#if !MIN_VERSION_base(4,7,0)
+import Control.Exception (mask_, onException)
+import Control.Monad (return)
+import Data.Function (($))
+import System.IO (IO)
+
+{-|
+  Like 'withMVar', but the @IO@ action in the second argument is executed
+  with asynchronous exceptions masked.
+
+  @since 4.7.0.0
+-}
+{-# INLINE withMVarMasked #-}
+withMVarMasked :: MVar a -> (a -> IO b) -> IO b
+withMVarMasked m io =
+  mask_ $ do
+    a <- takeMVar m
+    b <- io a `onException` putMVar m a
+    putMVar m a
+    return b
+#endif
diff --git a/src/Control/Exception/Compat.hs b/src/Control/Exception/Compat.hs
--- a/src/Control/Exception/Compat.hs
+++ b/src/Control/Exception/Compat.hs
@@ -7,7 +7,7 @@
 import Control.Exception as Base
 
 #if __GLASGOW_HASKELL__ <= 706
-import Prelude
+import Prelude.Compat
 deriving instance Ord ErrorCall
 deriving instance Eq ErrorCall
 #endif
diff --git a/src/Control/Monad/Compat.hs b/src/Control/Monad/Compat.hs
--- a/src/Control/Monad/Compat.hs
+++ b/src/Control/Monad/Compat.hs
@@ -1,15 +1,35 @@
 module Control.Monad.Compat (
   module Base
 , void
+, (<$!>)
 ) where
-
-import           Control.Monad as Base
+import Control.Monad as Base
 
 #if !MIN_VERSION_base(4,3,0)
+import Data.Function (const)
+import Data.Functor (Functor(..))
+#endif
 
-import           Prelude.Compat
+#if !MIN_VERSION_base(4,8,0)
+import Prelude.Compat (seq)
+#endif
 
+#if !MIN_VERSION_base(4,3,0)
 -- | @'void' value@ discards or ignores the result of evaluation, such as the return value of an 'IO' action.
 void :: Functor f => f a -> f ()
 void = fmap (const ())
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
+infixl 4 <$!>
+
+-- | Strict version of 'Data.Functor.<$>'.
+--
+-- /Since: 4.8.0.0/
+(<$!>) :: Monad m => (a -> b) -> m a -> m b
+{-# INLINE (<$!>) #-}
+f <$!> m = do
+  x <- m
+  let z = f x
+  z `seq` return z
 #endif
diff --git a/src/Data/Bits/Compat.hs b/src/Data/Bits/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bits/Compat.hs
@@ -0,0 +1,38 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Data.Bits.Compat (
+  module Base
+) where
+import Data.Bits as Base
+
+-- These instances are only valid if Bits isn't a subclass of Num (as Bool is
+-- not a Num instance), which is only true as of base-4.6.0.0 and later.
+#if MIN_VERSION_base(4,6,0) && !MIN_VERSION_base(4,7,0)
+import Prelude.Compat
+
+instance Bits Bool where
+    (.&.) = (&&)
+
+    (.|.) = (||)
+
+    xor = (/=)
+
+    complement = not
+
+    shift x 0 = x
+    shift _ _ = False
+
+    rotate x _ = x
+
+    bit 0 = True
+    bit _ = False
+
+    testBit x 0 = x
+    testBit _ _ = False
+
+    bitSize _ = 1
+
+    isSigned _ = False
+
+    popCount False = 0
+    popCount True  = 1
+#endif
diff --git a/src/Data/Bool/Compat.hs b/src/Data/Bool/Compat.hs
--- a/src/Data/Bool/Compat.hs
+++ b/src/Data/Bool/Compat.hs
@@ -12,6 +12,8 @@
 import Data.Bool
 
 #if !MIN_VERSION_base(4,7,0)
+import Data.Bits.Compat ()
+
 -- | Case analysis for the 'Bool' type.
 -- @bool a b p@ evaluates to @a@ when @p@ is @False@, and evaluates to @b@
 -- when @p@ is @True@.
diff --git a/src/Data/Either/Compat.hs b/src/Data/Either/Compat.hs
--- a/src/Data/Either/Compat.hs
+++ b/src/Data/Either/Compat.hs
@@ -7,6 +7,8 @@
 
 #if !MIN_VERSION_base(4,7,0)
 import Data.Bool (Bool(..))
+import Data.Traversable.Compat ()
+
 -- | Return `True` if the given value is a `Left`-value, `False` otherwise.
 --
 -- /Since: 4.7.0.0/
diff --git a/src/Data/Function/Compat.hs b/src/Data/Function/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Function/Compat.hs
@@ -0,0 +1,18 @@
+module Data.Function.Compat (
+  module Base
+, (&)
+) where
+import Data.Function as Base
+
+#if !MIN_VERSION_base(4,8,0)
+infixl 1 &
+
+-- | '&' is a reverse application operator.  This provides notational
+-- convenience.  Its precedence is one higher than that of the forward
+-- application operator '$', which allows '&' to be nested in '$'.
+--
+-- /Since: 4.8.0.0/
+(&) :: a -> (a -> b) -> b
+x & f = f x
+
+#endif
diff --git a/src/Data/List/Compat.hs b/src/Data/List/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/List/Compat.hs
@@ -0,0 +1,71 @@
+module Data.List.Compat (
+  module Base
+, dropWhileEnd
+, isSubsequenceOf
+, sortOn
+, uncons
+) where
+import Data.List as Base
+
+#if !MIN_VERSION_base(4,8,0)
+import Prelude.Compat hiding (foldr, null)
+import Data.Ord (comparing)
+#endif
+
+#if !MIN_VERSION_base(4,5,0)
+-- | The 'dropWhileEnd' function drops the largest suffix of a list
+-- in which the given predicate holds for all elements.  For example:
+--
+-- > dropWhileEnd isSpace "foo\n" == "foo"
+-- > dropWhileEnd isSpace "foo bar" == "foo bar"
+-- > dropWhileEnd isSpace ("foo\n" ++ undefined) == "foo" ++ undefined
+--
+-- /Since: 4.5.0.0/
+dropWhileEnd :: (a -> Bool) -> [a] -> [a]
+dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
+
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
+-- | The 'isSubsequenceOf' function takes two lists and returns 'True' if the
+-- first list is a subsequence of the second list.
+--
+-- @'isSubsequenceOf' x y@ is equivalent to @'elem' x ('subsequences' y)@.
+--
+-- /Since: 4.8.0.0/
+--
+-- ==== __Examples__
+--
+-- >>> isSubsequenceOf "GHC" "The Glorious Haskell Compiler"
+-- True
+-- >>> isSubsequenceOf ['a','d'..'z'] ['a'..'z']
+-- True
+-- >>> isSubsequenceOf [1..10] [10,9..0]
+-- False
+isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool
+isSubsequenceOf []    _                    = True
+isSubsequenceOf _     []                   = False
+isSubsequenceOf a@(x:a') (y:b) | x == y    = isSubsequenceOf a' b
+                               | otherwise = isSubsequenceOf a b
+
+-- | Sort a list by comparing the results of a key function applied to each
+-- element.  @sortOn f@ is equivalent to @sortBy . comparing f@, but has the
+-- performance advantage of only evaluating @f@ once for each element in the
+-- input list.  This is called the decorate-sort-undecorate paradigm, or
+-- Schwartzian transform.
+--
+-- /Since: 4.8.0.0/
+sortOn :: Ord b => (a -> b) -> [a] -> [a]
+sortOn f =
+  map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))
+
+-- | Decompose a list into its head and tail. If the list is empty,
+-- returns 'Nothing'. If the list is non-empty, returns @'Just' (x, xs)@,
+-- where @x@ is the head of the list and @xs@ its tail.
+--
+-- /Since: 4.8.0.0/
+uncons                  :: [a] -> Maybe (a, [a])
+uncons []               = Nothing
+uncons (x:xs)           = Just (x, xs)
+
+#endif
diff --git a/src/Data/Monoid/Compat.hs b/src/Data/Monoid/Compat.hs
--- a/src/Data/Monoid/Compat.hs
+++ b/src/Data/Monoid/Compat.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 module Data.Monoid.Compat (
         -- * Monoid typeclass
         Monoid(..),
@@ -18,6 +20,11 @@
 
 import Data.Monoid as Base
 
+#if !MIN_VERSION_base(4,7,0)
+import GHC.Generics.Compat ()
+import Prelude.Compat (Num)
+#endif
+
 #if !MIN_VERSION_base(4,5,0)
 infixr 6 <>
 
@@ -27,4 +34,9 @@
 (<>) :: Monoid m => m -> m -> m
 (<>) = mappend
 {-# INLINE (<>) #-}
+#endif
+
+#if !MIN_VERSION_base(4,7,0)
+deriving instance Num a => Num (Sum a)
+deriving instance Num a => Num (Product a)
 #endif
diff --git a/src/Data/Ord/Compat.hs b/src/Data/Ord/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Ord/Compat.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE StandaloneDeriving #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Data.Ord.Compat (
+  module Base
+) where
+import Data.Ord as Base
+
+#if MIN_VERSION_base(4,6,0) && !MIN_VERSION_base(4,7,0)
+import Prelude.Compat
+
+deriving instance Read a => Read (Down a)
+deriving instance Show a => Show (Down a)
+#endif
diff --git a/src/Data/Version/Compat.hs b/src/Data/Version/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Version/Compat.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving, TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Data.Version.Compat (
+  module Base
+, makeVersion
+) where
+import Data.Version as Base
+
+#if !MIN_VERSION_base(4,7,0)
+import Data.Data
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
+import Prelude.Compat
+
+# if MIN_VERSION_base(4,7,0)
+import GHC.Exts (IsList(..))
+# endif
+#endif
+
+#if !MIN_VERSION_base(4,7,0)
+deriving instance Data Version
+#endif
+
+#if !MIN_VERSION_base(4,8,0)
+-- | Construct tag-less 'Version'
+--
+-- /Since: 4.8.0.0/
+makeVersion :: [Int] -> Version
+makeVersion b = Version b []
+
+# if MIN_VERSION_base(4,7,0)
+-- | /Since: 4.8.0.0/
+instance IsList Version where
+  type (Item Version) = Int
+  fromList = makeVersion
+  toList = versionBranch
+# endif
+
+#endif
diff --git a/src/Debug/Trace/Compat.hs b/src/Debug/Trace/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Debug/Trace/Compat.hs
@@ -0,0 +1,58 @@
+module Debug.Trace.Compat (
+  module Base
+, traceId
+, traceShowId
+, traceM
+, traceShowM
+) where
+import Debug.Trace as Base
+
+#if !MIN_VERSION_base(4,7,0)
+import Prelude.Compat
+
+{-|
+Like 'trace' but returns the message instead of a third value.
+
+/Since: 4.7.0.0/
+-}
+traceId :: String -> String
+traceId a = trace a a
+
+{-|
+Like 'traceShow' but returns the shown value instead of a third value.
+
+/Since: 4.7.0.0/
+-}
+traceShowId :: (Show a) => a -> a
+traceShowId a = trace (show a) a
+
+{-|
+Like 'trace' but returning unit in an arbitrary monad. Allows for convenient
+use in do-notation. Note that the application of 'trace' is not an action in the
+monad, as 'traceIO' is in the 'IO' monad.
+
+> ... = do
+>   x <- ...
+>   traceM $ "x: " ++ show x
+>   y <- ...
+>   traceM $ "y: " ++ show y
+
+/Since: 4.7.0.0/
+-}
+traceM :: (Monad m) => String -> m ()
+traceM string = trace string $ return ()
+
+{-|
+Like 'traceM', but uses 'show' on the argument to convert it to a 'String'.
+
+> ... = do
+>   x <- ...
+>   traceMShow $ x
+>   y <- ...
+>   traceMShow $ x + y
+
+/Since: 4.7.0.0/
+-}
+traceShowM :: (Show a, Monad m) => a -> m ()
+traceShowM = traceM . show
+#endif
diff --git a/src/Foreign/Compat.hs b/src/Foreign/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Compat.hs
@@ -0,0 +1,11 @@
+module Foreign.Compat (
+  module Base
+, module Bits
+, module Storable
+, module Marshal
+) where
+import Foreign as Base
+
+import Data.Bits.Compat as Bits
+import Foreign.Marshal.Compat as Marshal
+import Foreign.Storable.Compat as Storable
diff --git a/src/Foreign/Marshal/Alloc/Compat.hs b/src/Foreign/Marshal/Alloc/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Marshal/Alloc/Compat.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Foreign.Marshal.Alloc.Compat (
+  module Base
+, calloc
+, callocBytes
+) where
+import Foreign.Marshal.Alloc as Base
+
+#if !MIN_VERSION_base(4,8,0)
+import Foreign.C.Types
+import Foreign.Ptr (Ptr, nullPtr)
+import Foreign.Storable.Compat (Storable(..))
+import GHC.IO.Exception
+import Prelude.Compat
+
+-- |Like 'malloc' but memory is filled with bytes of value zero.
+--
+{-# INLINE calloc #-}
+calloc :: Storable a => IO (Ptr a)
+calloc = doCalloc undefined
+  where
+    doCalloc       :: Storable b => b -> IO (Ptr b)
+    doCalloc dummy = callocBytes (sizeOf dummy)
+
+-- |Llike 'mallocBytes' but memory is filled with bytes of value zero.
+--
+callocBytes :: Int -> IO (Ptr a)
+callocBytes size = failWhenNULL "calloc" $ _calloc 1 (fromIntegral size)
+
+-- asserts that the pointer returned from the action in the second argument is
+-- non-null
+--
+failWhenNULL :: String -> IO (Ptr a) -> IO (Ptr a)
+failWhenNULL name f = do
+   addr <- f
+   if addr == nullPtr
+      then ioError (IOError Nothing ResourceExhausted name
+                                        "out of memory" Nothing Nothing)
+      else return addr
+
+foreign import ccall unsafe "stdlib.h calloc"  _calloc  :: CSize -> CSize -> IO (Ptr a)
+#endif
diff --git a/src/Foreign/Marshal/Array/Compat.hs b/src/Foreign/Marshal/Array/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Marshal/Array/Compat.hs
@@ -0,0 +1,27 @@
+module Foreign.Marshal.Array.Compat (
+  module Base
+, callocArray
+, callocArray0
+) where
+import Foreign.Marshal.Array as Base
+
+#if !MIN_VERSION_base(4,8,0)
+import Foreign.Marshal.Alloc.Compat
+import Foreign.Ptr (Ptr)
+import Foreign.Storable.Compat (Storable(..))
+import Prelude.Compat
+
+-- |Like 'mallocArray', but allocated memory is filled with bytes of value zero.
+--
+callocArray :: Storable a => Int -> IO (Ptr a)
+callocArray  = doCalloc undefined
+  where
+    doCalloc :: Storable a' => a' -> Int -> IO (Ptr a')
+    doCalloc dummy size  = callocBytes (size * sizeOf dummy)
+
+-- |Like 'callocArray0', but allocated memory is filled with bytes of value
+-- zero.
+--
+callocArray0 :: Storable a => Int -> IO (Ptr a)
+callocArray0 size  = callocArray (size + 1)
+#endif
diff --git a/src/Foreign/Marshal/Compat.hs b/src/Foreign/Marshal/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Marshal/Compat.hs
@@ -0,0 +1,9 @@
+module Foreign.Marshal.Compat (
+  module Base
+, module Alloc
+, module Array
+) where
+import Foreign.Marshal as Base
+
+import Foreign.Marshal.Alloc.Compat as Alloc
+import Foreign.Marshal.Array.Compat as Array
diff --git a/src/Foreign/Storable/Compat.hs b/src/Foreign/Storable/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Storable/Compat.hs
@@ -0,0 +1,42 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Foreign.Storable.Compat (
+  module Base
+, Storable(..)
+) where
+import Foreign.Storable as Base
+
+#if !MIN_VERSION_base(4,8,0)
+import Data.Complex (Complex(..), realPart)
+import Foreign.Ptr (castPtr)
+import GHC.Real (Ratio(..), (%))
+import Prelude.Compat
+
+-- The actual constraint in base-4.8.0.0 doesn't include RealFloat a, but it
+-- is needed in previous versions of base due to Complex having lots of
+-- RealFloat constraints in its functions' type signatures.
+instance (Storable a, RealFloat a) => Storable (Complex a) where
+    sizeOf a       = 2 * sizeOf (realPart a)
+    alignment a    = alignment (realPart a)
+    peek p           = do
+                        q <- return $ castPtr p
+                        r <- peek q
+                        i <- peekElemOff q 1
+                        return (r :+ i)
+    poke p (r :+ i)  = do
+                        q <-return $  (castPtr p)
+                        poke q r
+                        pokeElemOff q 1 i
+
+instance (Storable a, Integral a) => Storable (Ratio a) where
+    sizeOf (n :% _)    = 2 * sizeOf n
+    alignment (n :% _) = alignment n
+    peek p           = do
+                        q <- return $ castPtr p
+                        r <- peek q
+                        i <- peekElemOff q 1
+                        return (r % i)
+    poke p (r :% i)  = do
+                        q <-return $  (castPtr p)
+                        poke q r
+                        pokeElemOff q 1 i
+#endif
diff --git a/src/GHC/Generics/Compat.hs b/src/GHC/Generics/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/GHC/Generics/Compat.hs
@@ -0,0 +1,119 @@
+{-# LANGUAGE FlexibleContexts, StandaloneDeriving, TypeOperators #-}
+
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE DeriveGeneric #-}
+#endif
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module GHC.Generics.Compat (
+-- GHC.Generics is only available on GHC 7.2 and later, so we can't export anything
+-- if we're using a GHC prior to 7.2
+#if __GLASGOW_HASKELL__ < 702
+) where
+#else
+  module Base
+) where
+import           GHC.Generics as Base
+
+# if !MIN_VERSION_base(4,7,0)
+import           GHC.Read
+import           Prelude.Compat
+import qualified Text.ParserCombinators.ReadPrec as ReadPrec
+import           Text.Read.Lex
+
+-- Although DeriveGeneric has been around since GHC 7.2, various bugs cause
+-- the standalone-derived code below to fail to compile unless a fairly
+-- recent version of GHC is used.
+#  if __GLASGOW_HASKELL__ >= 706
+import           Control.Applicative
+import           Data.Monoid
+
+deriving instance Generic All
+deriving instance Generic Any
+deriving instance Generic (Const a b)
+deriving instance Generic (Dual a)
+deriving instance Generic (Endo a)
+deriving instance Generic (First a)
+deriving instance Generic (Last a)
+deriving instance Generic (Product a)
+deriving instance Generic (Sum a)
+deriving instance Generic (WrappedArrow a b c)
+deriving instance Generic (WrappedMonad m a)
+deriving instance Generic (ZipList a)
+
+deriving instance Generic1 (Const a)
+deriving instance Generic1 Dual
+deriving instance Generic1 First
+deriving instance Generic1 Last
+deriving instance Generic1 Product
+deriving instance Generic1 Sum
+deriving instance Generic1 (WrappedArrow a b)
+deriving instance Generic1 (WrappedMonad m)
+deriving instance Generic1 ZipList
+
+deriving instance Generic (U1 p)
+deriving instance Generic (Par1 p)
+deriving instance Generic (Rec1 f p)
+deriving instance Generic (K1 i c p)
+deriving instance Generic (M1 i c f p)
+deriving instance Generic ((f :+: g) p)
+deriving instance Generic ((f :*: g) p)
+deriving instance Generic ((f :.: g) p)
+#  endif
+
+deriving instance Eq (U1 p)
+deriving instance Ord (U1 p)
+deriving instance Read (U1 p)
+deriving instance Show (U1 p)
+
+deriving instance Eq p => Eq (Par1 p)
+deriving instance Ord p => Ord (Par1 p)
+deriving instance Read p => Read (Par1 p)
+deriving instance Show p => Show (Par1 p)
+
+deriving instance Eq (f p) => Eq (Rec1 f p)
+deriving instance Ord (f p) => Ord (Rec1 f p)
+deriving instance Read (f p) => Read (Rec1 f p)
+deriving instance Show (f p) => Show (Rec1 f p)
+
+deriving instance Eq c => Eq (K1 i c p)
+deriving instance Ord c => Ord (K1 i c p)
+deriving instance Read c => Read (K1 i c p)
+deriving instance Show c => Show (K1 i c p)
+
+deriving instance Eq (f p) => Eq (M1 i c f p)
+deriving instance Ord (f p) => Ord (M1 i c f p)
+deriving instance Read (f p) => Read (M1 i c f p)
+deriving instance Show (f p) => Show (M1 i c f p)
+
+deriving instance (Eq (f p), Eq (g p)) => Eq ((f :+: g) p)
+deriving instance (Ord (f p), Ord (g p)) => Ord ((f :+: g) p)
+deriving instance (Read (f p), Read (g p)) => Read ((f :+: g) p)
+deriving instance (Show (f p), Show (g p)) => Show ((f :+: g) p)
+
+deriving instance (Eq (f p), Eq (g p)) => Eq ((f :*: g) p)
+deriving instance (Ord (f p), Ord (g p)) => Ord ((f :*: g) p)
+-- Due to a GHC bug (https://ghc.haskell.org/trac/ghc/ticket/9830), the derived
+-- Read and Show instances for infix data constructors will use the wrong
+-- precedence (prior to GHC 7.10).
+-- We'll manually derive Read :*: and Show :*: instances to avoid this.
+instance (Read (f p), Read (g p)) => Read ((f :*: g) p) where
+    readPrec = parens . ReadPrec.prec 6 $ do
+        fp <- ReadPrec.step readPrec
+        Symbol ":*:" <- lexP
+        gp <- ReadPrec.step readPrec
+        return $ fp :*: gp
+    readListPrec = readListPrecDefault
+instance (Show (f p), Show (g p)) => Show ((f :*: g) p) where
+     showsPrec p (l :*: r) = showParen (p > sixPrec) $
+            showsPrec (sixPrec + 1) l
+         . showString " :*: "
+         . showsPrec (sixPrec + 1) r
+       where sixPrec = 6
+
+deriving instance Eq (f (g p)) => Eq ((f :.: g) p)
+deriving instance Ord (f (g p)) => Ord ((f :.: g) p)
+deriving instance Read (f (g p)) => Read ((f :.: g) p)
+deriving instance Show (f (g p)) => Show ((f :.: g) p)
+# endif
+
+#endif
diff --git a/src/System/Console/GetOpt/Compat.hs b/src/System/Console/GetOpt/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Console/GetOpt/Compat.hs
@@ -0,0 +1,23 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module System.Console.GetOpt.Compat (
+  module Base
+) where
+import System.Console.GetOpt as Base
+
+#if !MIN_VERSION_base(4,7,0)
+import Data.Function ((.))
+import Data.Functor (Functor(..))
+
+instance Functor ArgOrder where
+    fmap _ RequireOrder      = RequireOrder
+    fmap _ Permute           = Permute
+    fmap f (ReturnInOrder g) = ReturnInOrder (f . g)
+
+instance Functor OptDescr where
+    fmap f (Option a b argDescr c) = Option a b (fmap f argDescr) c
+
+instance Functor ArgDescr where
+    fmap f (NoArg a)    = NoArg (f a)
+    fmap f (ReqArg g s) = ReqArg (f . g) s
+    fmap f (OptArg g s) = OptArg (f . g) s
+#endif
diff --git a/src/System/Environment/Compat.hs b/src/System/Environment/Compat.hs
--- a/src/System/Environment/Compat.hs
+++ b/src/System/Environment/Compat.hs
@@ -18,7 +18,7 @@
 #endif
 
 #if !MIN_VERSION_base(4,6,0)
-import Prelude
+import Prelude.Compat
 -- | Return the value of the environment variable @var@, or @Nothing@ if
 -- there is no such value.
 --
diff --git a/src/System/Exit/Compat.hs b/src/System/Exit/Compat.hs
--- a/src/System/Exit/Compat.hs
+++ b/src/System/Exit/Compat.hs
@@ -11,7 +11,7 @@
 
 #if !MIN_VERSION_base(4,8,0)
 
-import Prelude
+import Prelude.Compat
 import System.IO
 
 -- | Write given error message to `stderr` and terminate with `exitFailure`.
diff --git a/src/Text/Read/Compat.hs b/src/Text/Read/Compat.hs
--- a/src/Text/Read/Compat.hs
+++ b/src/Text/Read/Compat.hs
@@ -26,7 +26,7 @@
 import qualified Text.Read.Lex as L
 
 #if !MIN_VERSION_base(4,6,0)
-import Prelude
+import Prelude.Compat
 import qualified Text.ParserCombinators.ReadP as P
 
 -- | Parse a string using the 'Read' instance.
