diff --git a/Control/DeepSeq.hs b/Control/DeepSeq.hs
--- a/Control/DeepSeq.hs
+++ b/Control/DeepSeq.hs
@@ -1,16 +1,21 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE DefaultSignatures #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeOperators #-}
-# if MIN_VERSION_array(0,4,0)
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE Safe #-}
-# endif
-#endif
+{-# LANGUAGE TypeOperators #-}
+
 #if __GLASGOW_HASKELL__ >= 706
 {-# LANGUAGE PolyKinds #-}
 #endif
+
+#if __GLASGOW_HASKELL__ >= 708
+{-# LANGUAGE EmptyCase #-}
+#endif
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.DeepSeq
@@ -21,21 +26,29 @@
 -- Stability   :  stable
 -- Portability :  portable
 --
--- This module provides an overloaded function, 'deepseq', for fully
--- evaluating data structures (that is, evaluating to \"Normal Form\").
+-- This module provides overloaded functions, such as 'deepseq' and
+-- 'rnf', for fully evaluating data structures (that is, evaluating to
+-- \"Normal Form\").
 --
 -- A typical use is to prevent resource leaks in lazy IO programs, by
 -- forcing all characters from a file to be read. For example:
 --
 -- > import System.IO
 -- > import Control.DeepSeq
+-- > import Control.Exception (evaluate)
 -- >
--- > main = do
--- >     h <- openFile "f" ReadMode
+-- > readFile' :: FilePath -> IO String
+-- > readFile' fn = do
+-- >     h <- openFile fn ReadMode
 -- >     s <- hGetContents h
--- >     s `deepseq` hClose h
+-- >     evaluate (rnf s)
+-- >     hClose h
 -- >     return s
 --
+-- __Note__: The example above should rather be written in terms of
+-- 'Control.Exception.bracket' to ensure releasing file-descriptors in
+-- a timely matter (see the description of 'force' for an example).
+--
 -- 'deepseq' differs from 'seq' as it traverses data structures deeply,
 -- for example, 'seq' will evaluate only to the first constructor in
 -- the list:
@@ -56,8 +69,20 @@
 --
 -- @since 1.1.0.0
 module Control.DeepSeq (
-     deepseq, ($!!), force,
-     NFData(..),
+     -- * 'NFData' class
+     NFData(rnf),
+     -- * Helper functions
+     deepseq,
+     force,
+     ($!!),
+     (<$!!>),
+     rwhnf,
+
+     -- * Liftings of the 'NFData' class
+     -- ** For unary constructors
+     NFData1(liftRnf), rnf1,
+     -- ** For binary constructors
+     NFData2(liftRnf2), rnf2,
   ) where
 
 import Control.Applicative
@@ -80,12 +105,22 @@
 
 #if MIN_VERSION_base(4,6,0)
 import Data.Ord ( Down(Down) )
+#else
+import Control.DeepSeq.BackDoor ( Down(Down) )
 #endif
 
 #if MIN_VERSION_base(4,7,0)
 import Data.Proxy ( Proxy(Proxy) )
 #endif
 
+#if MIN_VERSION_base(4,10,0)
+import Data.Type.Equality ( (:~:), (:~~:) )
+#elif MIN_VERSION_base(4,9,0)
+import Data.Type.Equality ( (:~:) )
+#elif MIN_VERSION_base(4,7,0)
+import Control.DeepSeq.BackDoor ( (:~:) )
+#endif
+
 #if MIN_VERSION_base(4,8,0)
 import Data.Functor.Identity ( Identity(..) )
 import Data.Typeable ( TypeRep, TyCon, rnfTypeRep, rnfTyCon )
@@ -100,43 +135,64 @@
 
 #if MIN_VERSION_base(4,9,0)
 import GHC.Stack.Types ( CallStack(..), SrcLoc(..) )
+import Data.Functor.Compose
+import qualified Data.Functor.Sum as Functor
+import qualified Data.Functor.Product as Functor
 #elif MIN_VERSION_base(4,8,1)
 import GHC.Stack ( CallStack(..) )
 import GHC.SrcLoc ( SrcLoc(..) )
 #endif
 
-#if __GLASGOW_HASKELL__ >= 702
 import GHC.Fingerprint.Type ( Fingerprint(..) )
 import GHC.Generics
 
 -- | Hidden internal type-class
-class GNFData f where
-  grnf :: f a -> ()
+class GNFData arity f where
+  grnf :: RnfArgs arity a -> f a -> ()
 
-instance GNFData V1 where
-  grnf = error "Control.DeepSeq.rnf: uninhabited type"
+instance GNFData arity V1 where
+#if __GLASGOW_HASKELL__ >= 708
+  grnf _ x = case x of {}
+#else
+  grnf _ !_ = error "Control.DeepSeq.rnf: uninhabited type"
+#endif
 
-instance GNFData U1 where
-  grnf U1 = ()
+data Zero
+data One
 
-instance NFData a => GNFData (K1 i a) where
-  grnf = rnf . unK1
+data RnfArgs arity a where
+  RnfArgs0 :: RnfArgs Zero a
+  RnfArgs1  :: (a -> ()) -> RnfArgs One a
+
+instance GNFData arity U1 where
+  grnf _ U1 = ()
+
+instance NFData a => GNFData arity (K1 i a) where
+  grnf _ = rnf . unK1
   {-# INLINEABLE grnf #-}
 
-instance GNFData a => GNFData (M1 i c a) where
-  grnf = grnf . unM1
+instance GNFData arity a => GNFData arity (M1 i c a) where
+  grnf args = grnf args . unM1
   {-# INLINEABLE grnf #-}
 
-instance (GNFData a, GNFData b) => GNFData (a :*: b) where
-  grnf (x :*: y) = grnf x `seq` grnf y
+instance (GNFData arity a, GNFData arity b) => GNFData arity (a :*: b) where
+  grnf args (x :*: y) = grnf args x `seq` grnf args y
   {-# INLINEABLE grnf #-}
 
-instance (GNFData a, GNFData b) => GNFData (a :+: b) where
-  grnf (L1 x) = grnf x
-  grnf (R1 x) = grnf x
+instance (GNFData arity a, GNFData arity b) => GNFData arity (a :+: b) where
+  grnf args (L1 x) = grnf args x
+  grnf args (R1 x) = grnf args x
   {-# INLINEABLE grnf #-}
-#endif
 
+instance GNFData One Par1 where
+    grnf (RnfArgs1 r) = r . unPar1
+
+instance NFData1 f => GNFData One (Rec1 f) where
+    grnf (RnfArgs1 r) = liftRnf r . unRec1
+
+instance (NFData1 f, GNFData One g) => GNFData One (f :.: g) where
+    grnf args = liftRnf (grnf args) . unComp1
+
 infixr 0 $!!
 
 -- | 'deepseq': fully evaluates the first argument, before returning the
@@ -198,10 +254,46 @@
 -- >   {- 'result' will be fully evaluated at this point -}
 -- >   return ()
 --
+-- Finally, here's an exception safe variant of the @readFile'@ example:
+--
+-- > readFile' :: FilePath -> IO String
+-- > readFile' fn = bracket (openFile fn ReadMode) hClose $ \h ->
+-- >                        evaluate . force =<< hGetContents h
+--
 -- @since 1.2.0.0
 force :: (NFData a) => a -> a
 force x = x `deepseq` x
 
+-- | Deeply strict version of 'Control.Applicative.<$>'.
+--
+-- @since 1.4.3.0
+(<$!!>) :: (Monad m, NFData b) => (a -> b) -> m a -> m b
+#if MIN_VERSION_base(4,8,0)
+-- Minor optimisation for AMP; this avoids the redundant indirection
+-- through 'return' in case GHC isn't smart enough to optimise it away
+-- on its own
+f <$!!> m = m >>= \x -> pure $!! f x
+#else
+f <$!!> m = m >>= \x -> return $!! f x
+#endif
+infixl 4 <$!!>
+
+-- | Reduce to weak head normal form
+--
+-- Equivalent to @\\x -> 'seq' x ()@.
+--
+-- Useful for defining 'NFData' for types for which NF=WHNF holds.
+--
+-- > data T = C1 | C2 | C3
+-- > instance NFData T where rnf = rwhnf
+--
+-- @since 1.4.3.0
+rwhnf :: a -> ()
+rwhnf = (`seq` ())
+{-# INLINE rwhnf #-}
+
+-- Note: the 'rwhnf' is defined point-free to help aggressive inlining
+
 -- | A class of types that can be fully evaluated.
 --
 -- @since 1.1.0.0
@@ -214,15 +306,18 @@
     -- Starting with GHC 7.2, you can automatically derive instances
     -- for types possessing a 'Generic' instance.
     --
+    -- Note: 'Generic1' can be auto-derived starting with GHC 7.4
+    --
     -- > {-# LANGUAGE DeriveGeneric #-}
     -- >
-    -- > import GHC.Generics (Generic)
+    -- > import GHC.Generics (Generic, Generic1)
     -- > import Control.DeepSeq
     -- >
     -- > data Foo a = Foo a String
-    -- >              deriving (Eq, Generic)
+    -- >              deriving (Eq, Generic, Generic1)
     -- >
     -- > instance NFData a => NFData (Foo a)
+    -- > instance NFData1 Foo
     -- >
     -- > data Colour = Red | Green | Blue
     -- >               deriving Generic
@@ -238,7 +333,7 @@
     -- > import Control.DeepSeq
     -- >
     -- > data Foo a = Foo a String
-    -- >              deriving (Eq, Generic, NFData)
+    -- >              deriving (Eq, Generic, Generic1, NFData, NFData1)
     -- >
     -- > data Colour = Red | Green | Blue
     -- >               deriving (Generic, NFData)
@@ -261,46 +356,110 @@
     --
     -- or alternatively
     --
+    -- > instance NFData Colour where rnf = rwhnf
+    --
+    -- or
+    --
     -- > {-# LANGUAGE BangPatterns #-}
     -- > instance NFData Colour where rnf !_ = ()
     --
     rnf :: a -> ()
 
-#if __GLASGOW_HASKELL__ >= 702
-    default rnf :: (Generic a, GNFData (Rep a)) => a -> ()
-    rnf = grnf . from
-#endif
+    default rnf :: (Generic a, GNFData Zero (Rep a)) => a -> ()
+    rnf = grnf RnfArgs0 . from
 
-instance NFData Int      where rnf !_ = ()
-instance NFData Word     where rnf !_ = ()
-instance NFData Integer  where rnf !_ = ()
-instance NFData Float    where rnf !_ = ()
-instance NFData Double   where rnf !_ = ()
+-- | A class of functors that can be fully evaluated.
+--
+-- @since 1.4.3.0
+class NFData1 f where
+    -- | 'liftRnf' should reduce its argument to normal form (that is, fully
+    -- evaluate all sub-components), given an argument to reduce @a@ arguments,
+    -- and then return '()'.
+    --
+    -- See 'rnf' for the generic deriving.
+    liftRnf :: (a -> ()) -> f a -> ()
 
-instance NFData Char     where rnf !_ = ()
-instance NFData Bool     where rnf !_ = ()
-instance NFData ()       where rnf !_ = ()
+    default liftRnf :: (Generic1 f, GNFData One (Rep1 f)) => (a -> ()) -> f a -> ()
+    liftRnf r = grnf (RnfArgs1 r) . from1
 
-instance NFData Int8     where rnf !_ = ()
-instance NFData Int16    where rnf !_ = ()
-instance NFData Int32    where rnf !_ = ()
-instance NFData Int64    where rnf !_ = ()
+-- | Lift the standard 'rnf' function through the type constructor.
+--
+-- @since 1.4.3.0
+rnf1 :: (NFData1 f, NFData a) => f a -> ()
+rnf1 = liftRnf rnf
 
-instance NFData Word8    where rnf !_ = ()
-instance NFData Word16   where rnf !_ = ()
-instance NFData Word32   where rnf !_ = ()
-instance NFData Word64   where rnf !_ = ()
+-- | A class of bifunctors that can be fully evaluated.
+--
+-- @since 1.4.3.0
+class NFData2 p where
+    -- | 'liftRnf2' should reduce its argument to normal form (that
+    -- is, fully evaluate all sub-components), given functions to
+    -- reduce @a@ and @b@ arguments respectively, and then return '()'.
+    --
+    -- __Note__: Unlike for the unary 'liftRnf', there is currently no
+    -- support for generically deriving 'liftRnf2'.
+    liftRnf2 :: (a -> ()) -> (b -> ()) -> p a b -> ()
 
+-- | Lift the standard 'rnf' function through the type constructor.
+--
+-- @since 1.4.3.0
+rnf2 :: (NFData2 p, NFData a, NFData b) => p a b -> ()
+rnf2 = liftRnf2 rnf rnf
+
+
+instance NFData Int      where rnf = rwhnf
+instance NFData Word     where rnf = rwhnf
+instance NFData Integer  where rnf = rwhnf
+instance NFData Float    where rnf = rwhnf
+instance NFData Double   where rnf = rwhnf
+
+instance NFData Char     where rnf = rwhnf
+instance NFData Bool     where rnf = rwhnf
+instance NFData Ordering where rnf = rwhnf
+instance NFData ()       where rnf = rwhnf
+
+instance NFData Int8     where rnf = rwhnf
+instance NFData Int16    where rnf = rwhnf
+instance NFData Int32    where rnf = rwhnf
+instance NFData Int64    where rnf = rwhnf
+
+instance NFData Word8    where rnf = rwhnf
+instance NFData Word16   where rnf = rwhnf
+instance NFData Word32   where rnf = rwhnf
+instance NFData Word64   where rnf = rwhnf
+
 #if MIN_VERSION_base(4,7,0)
 -- |@since 1.4.0.0
 instance NFData (Proxy a) where rnf Proxy = ()
+-- |@since 1.4.3.0
+instance NFData1 Proxy    where liftRnf _ Proxy = ()
+
+-- | @since 1.4.3.0
+instance NFData (a :~: b) where rnf = rwhnf
+-- | @since 1.4.3.0
+instance NFData1 ((:~:) a) where liftRnf _ = rwhnf
+-- | @since 1.4.3.0
+instance NFData2 (:~:) where liftRnf2 _ _ = rwhnf
 #endif
 
+#if MIN_VERSION_base(4,10,0)
+-- | @since 1.4.3.0
+instance NFData (a :~~: b) where rnf = rwhnf
+-- | @since 1.4.3.0
+instance NFData1 ((:~~:) a) where liftRnf _ = rwhnf
+-- | @since 1.4.3.0
+instance NFData2 (:~~:) where liftRnf2 _ _ = rwhnf
+#endif
+
 #if MIN_VERSION_base(4,8,0)
 -- |@since 1.4.0.0
 instance NFData a => NFData (Identity a) where
-    rnf = rnf . runIdentity
+    rnf = rnf1
 
+-- |@since 1.4.3.0
+instance NFData1 Identity where
+    liftRnf r = r . runIdentity
+
 -- | Defined as @'rnf' = 'absurd'@.
 --
 -- @since 1.4.0.0
@@ -308,60 +467,109 @@
     rnf = absurd
 
 -- |@since 1.4.0.0
-instance NFData Natural  where rnf !_ = ()
+instance NFData Natural  where rnf = rwhnf
 #endif
 
 -- |@since 1.3.0.0
-instance NFData (Fixed a) where rnf !_ = ()
+instance NFData (Fixed a) where rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 Fixed where liftRnf _ = rwhnf
 
 -- |This instance is for convenience and consistency with 'seq'.
 -- This assumes that WHNF is equivalent to NF for functions.
 --
 -- @since 1.3.0.0
-instance NFData (a -> b) where rnf !_ = ()
+instance NFData (a -> b) where rnf = rwhnf
 
 --Rational and complex numbers.
 
-#if __GLASGOW_HASKELL__ >= 711
+#if MIN_VERSION_base(4,9,0)
+-- | Available on @base >=4.9@
+--
+-- @since 1.4.3.0
+instance NFData1 Ratio where
+  liftRnf r x = r (numerator x) `seq` r (denominator x)
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g) => NFData1 (Compose f g) where
+  liftRnf r = liftRnf (liftRnf r) . getCompose
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g, NFData a) => NFData (Compose f g a) where
+  rnf = rnf1
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g) => NFData1 (Functor.Sum f g) where
+  liftRnf rnf0 (Functor.InL l) = liftRnf rnf0 l
+  liftRnf rnf0 (Functor.InR r) = liftRnf rnf0 r
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g, NFData a) => NFData (Functor.Sum f g a) where
+  rnf = rnf1
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g) => NFData1 (Functor.Product f g) where
+  liftRnf rnf0 (Functor.Pair f g) = liftRnf rnf0 f `seq` liftRnf rnf0 g
+
+-- | @since 1.4.3.0
+instance (NFData1 f, NFData1 g, NFData a) => NFData (Functor.Product f g a) where
+  rnf = rnf1
+
 instance NFData a => NFData (Ratio a) where
 #else
 instance (Integral a, NFData a) => NFData (Ratio a) where
 #endif
   rnf x = rnf (numerator x, denominator x)
 
-#if MIN_VERSION_base(4,4,0)
 instance (NFData a) => NFData (Complex a) where
-#else
-instance (RealFloat a, NFData a) => NFData (Complex a) where
-#endif
   rnf (x:+y) = rnf x `seq`
                rnf y `seq`
                ()
 
-instance NFData a => NFData (Maybe a) where
-    rnf Nothing  = ()
-    rnf (Just x) = rnf x
+instance NFData a => NFData (Maybe a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Maybe where
+    liftRnf _r Nothing  = ()
+    liftRnf  r (Just x) = r x
 
-instance (NFData a, NFData b) => NFData (Either a b) where
-    rnf (Left x)  = rnf x
-    rnf (Right y) = rnf y
+instance (NFData a, NFData b) => NFData (Either a b) where rnf = rnf1
+-- |@since 1.4.3.0
+instance (NFData a) => NFData1 (Either a) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance NFData2 Either where
+    liftRnf2  l _r (Left x)  = l x
+    liftRnf2 _l  r (Right y) = r y
 
 -- |@since 1.3.0.0
 instance NFData Data.Version.Version where
     rnf (Data.Version.Version branch tags) = rnf branch `seq` rnf tags
 
-instance NFData a => NFData [a] where
-    rnf [] = ()
-    rnf (x:xs) = rnf x `seq` rnf xs
+instance NFData a => NFData [a] where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 [] where
+    liftRnf r = go
+      where
+        go [] = ()
+        go (x:xs) = r x `seq` go xs
 
 -- |@since 1.4.0.0
-instance NFData a => NFData (ZipList a) where
-    rnf = rnf . getZipList
+instance NFData a => NFData (ZipList a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 ZipList where
+    liftRnf r = liftRnf r . getZipList
 
 -- |@since 1.4.0.0
 instance NFData a => NFData (Const a b) where
     rnf = rnf . getConst
+-- |@since 1.4.3.0
+instance NFData a => NFData1 (Const a) where
+    liftRnf _ = rnf . getConst
+-- |@since 1.4.3.0
+instance NFData2 Const where
+    liftRnf2 r _ = r . getConst
 
+-- We should use MIN_VERSION array(0,5,1,1) but that's not possible.
+-- There isn't an underscore to not break C preprocessor
 #if __GLASGOW_HASKELL__ >= 711
 instance (NFData a, NFData b) => NFData (Array a b) where
 #else
@@ -369,49 +577,77 @@
 #endif
     rnf x = rnf (bounds x, Data.Array.elems x)
 
-#if MIN_VERSION_base(4,6,0)
--- |@since 1.4.0.0
-instance NFData a => NFData (Down a) where
-    rnf (Down x) = rnf x
+#if __GLASGOW_HASKELL__ >= 711
+-- |@since 1.4.3.0
+instance (NFData a) => NFData1 (Array a) where
+#else
+-- |@since 1.4.3.0
+instance (Ix a, NFData a) => NFData1 (Array a) where
 #endif
+    liftRnf r x = rnf (bounds x) `seq` liftRnf r (Data.Array.elems x)
 
+#if __GLASGOW_HASKELL__ >= 711
+-- |@since 1.4.3.0
+instance NFData2 Array where
+    liftRnf2 r r' x = liftRnf2 r r (bounds x) `seq` liftRnf r' (Data.Array.elems x)
+#endif
+
 -- |@since 1.4.0.0
-instance NFData a => NFData (Dual a) where
-    rnf = rnf . getDual
+instance NFData a => NFData (Down a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Down where
+    liftRnf r (Down x) = r x
 
 -- |@since 1.4.0.0
-instance NFData a => NFData (Mon.First a) where
-    rnf = rnf . Mon.getFirst
+instance NFData a => NFData (Dual a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Dual where
+    liftRnf r (Dual x) = r x
 
 -- |@since 1.4.0.0
-instance NFData a => NFData (Mon.Last a) where
-    rnf = rnf . Mon.getLast
+instance NFData a => NFData (Mon.First a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Mon.First  where
+    liftRnf r (Mon.First x) = liftRnf r x
 
 -- |@since 1.4.0.0
+instance NFData a => NFData (Mon.Last a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Mon.Last  where
+    liftRnf r (Mon.Last  x) = liftRnf r x
+
+-- |@since 1.4.0.0
 instance NFData Any where rnf = rnf . getAny
 
 -- |@since 1.4.0.0
 instance NFData All where rnf = rnf . getAll
 
 -- |@since 1.4.0.0
-instance NFData a => NFData (Sum a) where
-    rnf = rnf . getSum
+instance NFData a => NFData (Sum a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Sum where
+    liftRnf r (Sum x) = r x
 
 -- |@since 1.4.0.0
-instance NFData a => NFData (Product a) where
-    rnf = rnf . getProduct
+instance NFData a => NFData (Product a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Product where
+    liftRnf r (Product x) = r x
 
 -- |@since 1.4.0.0
 instance NFData (StableName a) where
-    rnf !_ = () -- assumes `data StableName a = StableName (StableName# a)`
+    rnf = rwhnf -- assumes `data StableName a = StableName (StableName# a)`
+-- |@since 1.4.3.0
+instance NFData1 StableName where
+    liftRnf _ = rwhnf
 
 -- |@since 1.4.0.0
 instance NFData ThreadId where
-    rnf !_ = () -- assumes `data ThreadId = ThreadId ThreadId#`
+    rnf = rwhnf -- assumes `data ThreadId = ThreadId ThreadId#`
 
 -- |@since 1.4.0.0
 instance NFData Unique where
-    rnf !_ = () -- assumes `newtype Unique = Unique Integer`
+    rnf = rwhnf -- assumes `newtype Unique = Unique Integer`
 
 #if MIN_VERSION_base(4,8,0)
 -- | __NOTE__: Only defined for @base-4.8.0.0@ and later
@@ -431,131 +667,152 @@
 --
 -- @since 1.4.2.0
 instance NFData (IORef a) where
-  rnf !_ = ()
+    rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 IORef where
+    liftRnf _ = rwhnf
 
 -- | __NOTE__: Only strict in the reference and not the referenced value.
 --
 -- @since 1.4.2.0
 instance NFData (STRef s a) where
-  rnf !_ = ()
+    rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 (STRef s) where
+    liftRnf _ = rwhnf
+-- |@since 1.4.3.0
+instance NFData2 STRef where
+    liftRnf2 _ _ = rwhnf
 
 -- | __NOTE__: Only strict in the reference and not the referenced value.
 --
 -- @since 1.4.2.0
 instance NFData (MVar a) where
-  rnf !_ = ()
+  rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 MVar where
+    liftRnf _ = rwhnf
 
 ----------------------------------------------------------------------------
 -- GHC Specifics
 
-#if __GLASGOW_HASKELL__ >= 702
 -- |@since 1.4.0.0
 instance NFData Fingerprint where
     rnf (Fingerprint _ _) = ()
-#endif
 
 ----------------------------------------------------------------------------
 -- Foreign.Ptr
 
 -- |@since 1.4.2.0
-instance NFData (Ptr a) where rnf !_ = ()
+instance NFData (Ptr a) where
+    rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 Ptr where
+    liftRnf _ = rwhnf
 
 -- |@since 1.4.2.0
-instance NFData (FunPtr a) where rnf !_ = ()
+instance NFData (FunPtr a) where
+    rnf = rwhnf
+-- |@since 1.4.3.0
+instance NFData1 FunPtr where
+    liftRnf _ = rwhnf
 
 ----------------------------------------------------------------------------
 -- Foreign.C.Types
 
 -- |@since 1.4.0.0
-instance NFData CChar where rnf !_ = ()
+instance NFData CChar where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CSChar where rnf !_ = ()
+instance NFData CSChar where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CUChar where rnf !_ = ()
+instance NFData CUChar where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CShort where rnf !_ = ()
+instance NFData CShort where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CUShort where rnf !_ = ()
+instance NFData CUShort where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CInt where rnf !_ = ()
+instance NFData CInt where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CUInt where rnf !_ = ()
+instance NFData CUInt where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CLong where rnf !_ = ()
+instance NFData CLong where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CULong where rnf !_ = ()
+instance NFData CULong where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CPtrdiff where rnf !_ = ()
+instance NFData CPtrdiff where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CSize where rnf !_ = ()
+instance NFData CSize where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CWchar where rnf !_ = ()
+instance NFData CWchar where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CSigAtomic where rnf !_ = ()
+instance NFData CSigAtomic where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CLLong where rnf !_ = ()
+instance NFData CLLong where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CULLong where rnf !_ = ()
+instance NFData CULLong where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CIntPtr where rnf !_ = ()
+instance NFData CIntPtr where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CUIntPtr where rnf !_ = ()
+instance NFData CUIntPtr where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CIntMax where rnf !_ = ()
+instance NFData CIntMax where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CUIntMax where rnf !_ = ()
+instance NFData CUIntMax where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CClock where rnf !_ = ()
+instance NFData CClock where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CTime where rnf !_ = ()
+instance NFData CTime where rnf = rwhnf
 
-#if MIN_VERSION_base(4,4,0)
 -- |@since 1.4.0.0
-instance NFData CUSeconds where rnf !_ = ()
+instance NFData CUSeconds where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CSUSeconds where rnf !_ = ()
-#endif
+instance NFData CSUSeconds where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CFloat where rnf !_ = ()
+instance NFData CFloat where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CDouble where rnf !_ = ()
+instance NFData CDouble where rnf = rwhnf
 
 -- NOTE: The types `CFile`, `CFPos`, and `CJmpBuf` below are not
 -- newtype wrappers rather defined as field-less single-constructor
 -- types.
 
 -- |@since 1.4.0.0
-instance NFData CFile where rnf !_ = ()
+instance NFData CFile where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CFpos where rnf !_ = ()
+instance NFData CFpos where rnf = rwhnf
 
 -- |@since 1.4.0.0
-instance NFData CJmpBuf where rnf !_ = ()
+instance NFData CJmpBuf where rnf = rwhnf
 
+#if MIN_VERSION_base(4,10,0)
+-- | @since 1.4.3.0
+instance NFData CBool where rnf = rwhnf
+#endif
+
 ----------------------------------------------------------------------------
 -- System.Exit
 
@@ -569,36 +826,54 @@
 
 #if MIN_VERSION_base(4,9,0)
 -- |@since 1.4.2.0
-instance NFData a => NFData (NonEmpty a) where
-  rnf (x :| xs) = rnf x `seq` rnf xs
+instance NFData a => NFData (NonEmpty a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 NonEmpty where
+  liftRnf r (x :| xs) = r x `seq` liftRnf r xs
 
 -- |@since 1.4.2.0
-instance NFData a => NFData (Min a) where
-  rnf (Min a) = rnf a
+instance NFData a => NFData (Min a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Min where
+  liftRnf r (Min a) = r a
 
 -- |@since 1.4.2.0
-instance NFData a => NFData (Max a) where
-  rnf (Max a) = rnf a
+instance NFData a => NFData (Max a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Max where
+  liftRnf r (Max a) = r a
 
 -- |@since 1.4.2.0
-instance (NFData a, NFData b) => NFData (Arg a b) where
-  rnf (Arg a b) = rnf a `seq` rnf b `seq` ()
+instance (NFData a, NFData b) => NFData (Arg a b) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a) => NFData1 (Arg a) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance NFData2 Arg where
+  liftRnf2 r r' (Arg a b) = r a `seq` r' b `seq` ()
 
 -- |@since 1.4.2.0
-instance NFData a => NFData (Semi.First a) where
-  rnf (Semi.First a) = rnf a
+instance NFData a => NFData (Semi.First a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Semi.First where
+  liftRnf r (Semi.First a) = r a
 
 -- |@since 1.4.2.0
-instance NFData a => NFData (Semi.Last a) where
-  rnf (Semi.Last a) = rnf a
+instance NFData a => NFData (Semi.Last a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Semi.Last where
+  liftRnf r (Semi.Last a) = r a
 
 -- |@since 1.4.2.0
-instance NFData m => NFData (WrappedMonoid m) where
-  rnf (WrapMonoid a) = rnf a
+instance NFData m => NFData (WrappedMonoid m) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 WrappedMonoid where
+  liftRnf r (WrapMonoid a) = r a
 
 -- |@since 1.4.2.0
-instance NFData a => NFData (Option a) where
-  rnf (Option a) = rnf a
+instance NFData a => NFData (Option a) where rnf = rnf1
+-- |@since 1.4.3.0
+instance NFData1 Option where
+  liftRnf r (Option a) = liftRnf r a
 #endif
 
 ----------------------------------------------------------------------------
@@ -636,69 +911,80 @@
 ----------------------------------------------------------------------------
 -- Tuples
 
-instance (NFData a, NFData b) => NFData (a,b) where
-  rnf (x,y) = rnf x `seq` rnf y
+instance (NFData a, NFData b) => NFData (a,b) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a) => NFData1 ((,) a) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance NFData2 (,) where
+  liftRnf2 r r' (x,y) = r x `seq` r' y
 
-instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
-  rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z
+-- Code below is generated, see generate-nfdata-tuple.hs
+instance (NFData a1, NFData a2, NFData a3) =>
+         NFData (a1, a2, a3) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2) =>
+         NFData1 ((,,) a1 a2) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1) =>
+         NFData2 ((,,) a1) where
+  liftRnf2 r r' (x1,x2,x3) = rnf x1 `seq` r x2 `seq` r' x3
 
-instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
-  rnf (x1,x2,x3,x4) = rnf x1 `seq`
-                      rnf x2 `seq`
-                      rnf x3 `seq`
-                      rnf x4
+instance (NFData a1, NFData a2, NFData a3, NFData a4) =>
+         NFData (a1, a2, a3, a4) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3) =>
+         NFData1 ((,,,) a1 a2 a3) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2) =>
+         NFData2 ((,,,) a1 a2) where
+  liftRnf2 r r' (x1,x2,x3,x4) = rnf x1 `seq` rnf x2 `seq` r x3 `seq` r' x4
 
 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) =>
-         NFData (a1, a2, a3, a4, a5) where
-  rnf (x1, x2, x3, x4, x5) =
-                  rnf x1 `seq`
-                  rnf x2 `seq`
-                  rnf x3 `seq`
-                  rnf x4 `seq`
-                  rnf x5
+         NFData (a1, a2, a3, a4, a5) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4) =>
+         NFData1 ((,,,,) a1 a2 a3 a4) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3) =>
+         NFData2 ((,,,,) a1 a2 a3) where
+  liftRnf2 r r' (x1,x2,x3,x4,x5) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` r x4 `seq` r' x5
 
 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) =>
-         NFData (a1, a2, a3, a4, a5, a6) where
-  rnf (x1, x2, x3, x4, x5, x6) =
-                  rnf x1 `seq`
-                  rnf x2 `seq`
-                  rnf x3 `seq`
-                  rnf x4 `seq`
-                  rnf x5 `seq`
-                  rnf x6
+         NFData (a1, a2, a3, a4, a5, a6) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) =>
+         NFData1 ((,,,,,) a1 a2 a3 a4 a5) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4) =>
+         NFData2 ((,,,,,) a1 a2 a3 a4) where
+  liftRnf2 r r' (x1,x2,x3,x4,x5,x6) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` r x5 `seq` r' x6
 
 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) =>
-         NFData (a1, a2, a3, a4, a5, a6, a7) where
-  rnf (x1, x2, x3, x4, x5, x6, x7) =
-                  rnf x1 `seq`
-                  rnf x2 `seq`
-                  rnf x3 `seq`
-                  rnf x4 `seq`
-                  rnf x5 `seq`
-                  rnf x6 `seq`
-                  rnf x7
+         NFData (a1, a2, a3, a4, a5, a6, a7) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) =>
+         NFData1 ((,,,,,,) a1 a2 a3 a4 a5 a6) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) =>
+         NFData2 ((,,,,,,) a1 a2 a3 a4 a5) where
+  liftRnf2 r r' (x1,x2,x3,x4,x5,x6,x7) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` r x6 `seq` r' x7
 
 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) =>
-         NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
-  rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
-                  rnf x1 `seq`
-                  rnf x2 `seq`
-                  rnf x3 `seq`
-                  rnf x4 `seq`
-                  rnf x5 `seq`
-                  rnf x6 `seq`
-                  rnf x7 `seq`
-                  rnf x8
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) =>
+         NFData1 ((,,,,,,,) a1 a2 a3 a4 a5 a6 a7) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) =>
+         NFData2 ((,,,,,,,) a1 a2 a3 a4 a5 a6) where
+  liftRnf2 r r' (x1,x2,x3,x4,x5,x6,x7,x8) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` r x7 `seq` r' x8
 
 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) =>
-         NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
-  rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
-                  rnf x1 `seq`
-                  rnf x2 `seq`
-                  rnf x3 `seq`
-                  rnf x4 `seq`
-                  rnf x5 `seq`
-                  rnf x6 `seq`
-                  rnf x7 `seq`
-                  rnf x8 `seq`
-                  rnf x9
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where rnf = rnf2
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) =>
+         NFData1 ((,,,,,,,,) a1 a2 a3 a4 a5 a6 a7 a8) where liftRnf = liftRnf2 rnf
+-- |@since 1.4.3.0
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) =>
+         NFData2 ((,,,,,,,,) a1 a2 a3 a4 a5 a6 a7) where
+  liftRnf2 r r' (x1,x2,x3,x4,x5,x6,x7,x8,x9) = rnf x1 `seq` rnf x2 `seq` rnf x3 `seq` rnf x4 `seq` rnf x5 `seq` rnf x6 `seq` rnf x7 `seq` r x8 `seq` r' x9
diff --git a/Control/DeepSeq/BackDoor.hs b/Control/DeepSeq/BackDoor.hs
new file mode 100644
--- /dev/null
+++ b/Control/DeepSeq/BackDoor.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE CPP #-}
+
+-- | Hack to keep Control.DeepSeq SAFE-inferred
+--
+-- This module only re-export reasonably safe entities from non-safe
+-- modules when there is no safe alternative
+
+#if MIN_VERSION_base(4,9,0) || (MIN_VERSION_base(4,6,0) && !MIN_VERSION_base(4,7,0))
+{-# LANGUAGE Safe #-}
+
+module Control.DeepSeq.BackDoor
+       {-# WARNING "This module is empty! Do not import me!" #-}
+       () where
+
+#else
+{-# LANGUAGE Trustworthy #-}
+
+module Control.DeepSeq.BackDoor
+    ( module X
+    ) where
+
+#if !(MIN_VERSION_base(4,6,0))
+-- not SAFE
+import GHC.Exts as X ( Down(Down) )
+#endif
+
+#if MIN_VERSION_base(4,10,0)
+-- Data.Type.Equality SAFE starting with base-4.10
+#elif MIN_VERSION_base(4,7,0)
+import Data.Type.Equality as X ( (:~:) )
+#endif
+
+#endif
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,45 @@
 # Changelog for [`deepseq` package](http://hackage.haskell.org/package/deepseq)
 
+## 1.4.3.0 *Apr 2017*
+
+  * Bundled with GHC 8.2.1
+
+  * Drop support for GHC 7.0 & GHC 7.2
+
+  * Changed strictness behavior of generic `NFData` instances for
+    constructor-less data types. Before, a generic `rnf`
+    implementation would always `error` on a data type with no
+    constructors. Now, it will force the argument, so if the argument
+    is a diverging computation, a generic `rnf` implementation will
+    actually trigger the diverging computation.
+    ([#19](https://github.com/haskell/deepseq/issues/19))
+
+  * Add new `rwhnf` function defined as `rwhnf !_ = ()`
+    ([#3](https://github.com/haskell/deepseq/issues/3))
+
+  * Add `(<$!!>) :: (Monad m, NFData b) => (a -> b) -> m a -> m b`
+    ([#13](https://github.com/haskell/deepseq/issues/13))
+
+  * Add `NFData1` and `NFData2` type classes
+    ([#8](https://github.com/haskell/deepseq/issues/8))
+
+  * Add `NFData` instance for `Down` for `base` versions prior to
+    `base-4.6.0` which didn't yet export it via `Data.Ord`
+    ([#28](https://github.com/haskell/deepseq/pull/28))
+
+  * Add `NFData` instance for `Foreign.C.Types.CBool`
+    ([#33](https://github.com/haskell/deepseq/pull/33))
+
+  * Add `NFData` instance for `Ordering`
+    ([#25](https://github.com/haskell/deepseq/pull/25))
+
+  * Add `NFData1` and `NFData` instances for `Data.Functor.{Compose,Sum,Product}`
+    ([#30](https://github.com/haskell/deepseq/pull/30))
+
+  * Add `NFData`, `NFData1`, and `NFData2` instances for `(:~:)` and `(:~~:)`
+    from `Data.Type.Equality`
+    ([#31](https://github.com/haskell/deepseq/issues/31))
+
 ## 1.4.2.0  *Apr 2016*
 
   * Bundled with GHC 8.0.1
diff --git a/deepseq.cabal b/deepseq.cabal
--- a/deepseq.cabal
+++ b/deepseq.cabal
@@ -1,5 +1,5 @@
 name:           deepseq
-version:        1.4.2.0
+version:        1.4.3.0
 -- NOTE: Don't forget to update ./changelog.md
 license:        BSD3
 license-file:   LICENSE
@@ -22,12 +22,12 @@
     data types.
 build-type:     Simple
 cabal-version:  >=1.10
-tested-with:    GHC==8.0.1,
+tested-with:    GHC==8.2.1,
+                GHC==8.0.2, GHC==8.0.1,
                 GHC==7.10.3, GHC==7.10.2, GHC==7.10.1,
                 GHC==7.8.4, GHC==7.8.3, GHC==7.8.2, GHC==7.8.1,
                 GHC==7.6.3, GHC==7.6.2, GHC==7.6.1,
-                GHC==7.4.2, GHC==7.4.1, GHC==7.2.2, GHC==7.2.1,
-                GHC==7.0.4, GHC==7.0.3, GHC==7.0.2, GHC==7.0.1
+                GHC==7.4.2, GHC==7.4.1
 
 extra-source-files: changelog.md
 
@@ -41,32 +41,35 @@
     BangPatterns
     CPP
 
-  if impl(ghc>=7.2)
-    -- Enable Generics-backed DefaultSignatures for `rnf`
-    other-extensions:
-      DefaultSignatures
-      FlexibleContexts
-      Safe
-      TypeOperators
+  -- Enable Generics-backed DefaultSignatures for `rnf`
+  other-extensions:
+    DefaultSignatures
+    GADTs
+    FlexibleContexts
+    FlexibleInstances
+    MultiParamTypeClasses
+    Safe
+    TypeOperators
 
-    -- GHC.Generics lived in `ghc-prim` for GHC 7.2 & GHC 7.4
-    if impl(ghc < 7.6)
-      build-depends: ghc-prim == 0.2.*
+  -- GHC.Generics lived in `ghc-prim` for GHC 7.2 & GHC 7.4
+  if impl(ghc == 7.4.*)
+    build-depends: ghc-prim == 0.2.*
 
-  if impl(ghc < 7.4)
-    build-depends: array < 0.4
+  if impl(ghc>=7.6)
+    other-extensions: PolyKinds
 
-  build-depends: base       >= 4.3 && < 4.10,
-                 array      >= 0.3 && < 0.6
+  if impl(ghc>=7.8)
+    other-extensions: EmptyCase
+
+  build-depends: base       >= 4.5 && < 4.11,
+                 array      >= 0.4 && < 0.6
   ghc-options: -Wall
 
   exposed-modules: Control.DeepSeq
-
+  other-modules:   Control.DeepSeq.BackDoor
 
 test-suite deepseq-generics-tests
     default-language:    Haskell2010
-    if !impl(ghc>=7.2)
-        buildable: False
     type:                exitcode-stdio-1.0
     hs-source-dirs:      . tests
     main-is:             Main.hs
@@ -86,7 +89,8 @@
     build-depends:
         array,
         base,
+        ghc-prim,
         -- end of packages with inherited version constraints
         test-framework == 0.8.*,
         test-framework-hunit == 0.3.*,
-        HUnit >= 1.2 && < 1.4
+        HUnit >= 1.2 && < 1.7
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -90,7 +90,11 @@
 
 ----------------------------------------------------------------------------
 
-case_1, case_2, case_3, case_4_1, case_4_2, case_4_3, case_4_4 :: Test.Framework.Test
+case_1, case_2, case_3 :: Test.Framework.Test
+case_4_1, case_4_2, case_4_3, case_4_4 :: Test.Framework.Test
+#if __GLASGOW_HASKELL__ >= 706
+case_4_1b, case_4_2b, case_4_3b, case_4_4b :: Test.Framework.Test
+#endif
 
 newtype Case1 = Case1 Int
               deriving (Generic)
@@ -125,10 +129,18 @@
 data Case4 a = Case4a
              | Case4b a a
              | Case4c a (Case4 a)
-             deriving (Generic)
+             deriving ( Generic
+#if __GLASGOW_HASKELL__ >= 706
+                      , Generic1
+#endif
+                      )
 
 instance NFData a => NFData (Case4 a)
 
+#if __GLASGOW_HASKELL__ >= 706
+instance NFData1 Case4
+#endif
+
 case_4_1 = testCase "Case4.1" $ withSeqState 0x0 $ do
     evaluate $ rnf $ (Case4a :: Case4 SeqSet)
 
@@ -144,9 +156,32 @@
     genCase n | n > 1      = Case4c (SeqSet n) (genCase (n-1))
               | otherwise  = Case4b (SeqSet 0) (SeqSet 1)
 
+#if __GLASGOW_HASKELL__ >= 706
+case_4_1b = testCase "Case4.1b" $ withSeqState 0x0 $ do
+    evaluate $ rnf1 $ (Case4a :: Case4 SeqSet)
+
+case_4_2b = testCase "Case4.2b" $ withSeqState 0x3 $ do
+    evaluate $ rnf1 $ (Case4b (SeqSet 0) (SeqSet 1) :: Case4 SeqSet)
+
+case_4_3b = testCase "Case4.3b" $ withSeqState (bit 55) $ do
+    evaluate $ rnf1 $ (Case4b SeqIgnore (SeqSet 55) :: Case4 SeqSet)
+
+case_4_4b = testCase "Case4.4b" $ withSeqState 0xffffffffffffffff $ do
+    evaluate $ rnf1 $ (genCase 63)
+  where
+    genCase n | n > 1      = Case4c (SeqSet n) (genCase (n-1))
+              | otherwise  = Case4b (SeqSet 0) (SeqSet 1)
+#endif
+
 ----------------------------------------------------------------------------
 
 main :: IO ()
 main = defaultMain [tests]
   where
-    tests = testGroup "" [case_1, case_2, case_3, case_4_1, case_4_2, case_4_3, case_4_4]
+    tests = testGroup ""
+        [ case_1, case_2, case_3
+        , case_4_1, case_4_2, case_4_3, case_4_4
+#if __GLASGOW_HASKELL__ >= 706
+        , case_4_1b, case_4_2b, case_4_3b, case_4_4b
+#endif
+        ]
