diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,9 @@
+## Version 1.2.6.0
+
+ * Add support for type-indexed `Typeable`.
+
+ * Rework the `Generic` hashable for sums.
+
 ## Version 1.2.5.0
 
   * Add `Hashable1` and `Hashable2`
diff --git a/Data/Hashable/Class.hs b/Data/Hashable/Class.hs
--- a/Data/Hashable/Class.hs
+++ b/Data/Hashable/Class.hs
@@ -1,5 +1,14 @@
 {-# LANGUAGE BangPatterns, CPP, ForeignFunctionInterface, MagicHash,
-             ScopedTypeVariables, UnliftedFFITypes, DeriveDataTypeable #-}
+             ScopedTypeVariables, UnliftedFFITypes #-}
+
+#if __GLASGOW_HASKELL__ < 710
+{-# LANGUAGE DeriveDataTypeable #-}
+#endif
+
+#if __GLASGOW_HASKELL__ >= 801
+{-# LANGUAGE PolyKinds #-} -- For TypeRep instances
+#endif
+
 #ifdef GENERICS
 {-# LANGUAGE DefaultSignatures, FlexibleContexts, GADTs,
     MultiParamTypeClasses, EmptyDataDecls #-}
@@ -56,9 +65,9 @@
 
 import Control.Applicative (Const(..))
 import Control.Exception (assert)
+import Control.DeepSeq (NFData(rnf))
 import Data.Bits (shiftL, shiftR, xor)
 import qualified Data.ByteString as B
-import qualified Data.ByteString.Internal as B
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.ByteString.Unsafe as B
 import Data.Int (Int8, Int16, Int32, Int64)
@@ -68,7 +77,6 @@
 import qualified Data.Text.Array as TA
 import qualified Data.Text.Internal as T
 import qualified Data.Text.Lazy as TL
-import Data.Typeable (Typeable, TypeRep)
 import Data.Version (Version(..))
 import Data.Word (Word8, Word16, Word32, Word64)
 import Foreign.C (CString)
@@ -78,7 +86,7 @@
 import GHC.Base (ByteArray#)
 import GHC.Conc (ThreadId(..))
 import GHC.Prim (ThreadId#)
-import System.IO.Unsafe (unsafePerformIO)
+import System.IO.Unsafe (unsafeDupablePerformIO)
 import System.Mem.StableName
 import Data.Unique (Unique, hashUnique)
 
@@ -101,14 +109,17 @@
 import GHC.Generics
 #endif
 
-#if __GLASGOW_HASKELL__ >= 710
-import Data.Typeable (typeRepFingerprint)
+#if   __GLASGOW_HASKELL__ >= 801
+import Type.Reflection (typeRepFingerprint, Typeable, TypeRep, SomeTypeRep(..))
 import GHC.Fingerprint.Type(Fingerprint(..))
+#elif __GLASGOW_HASKELL__ >= 710
+import Data.Typeable (typeRepFingerprint, Typeable, TypeRep)
+import GHC.Fingerprint.Type(Fingerprint(..))
 #elif __GLASGOW_HASKELL__ >= 702
-import Data.Typeable.Internal (TypeRep (..))
+import Data.Typeable.Internal (Typeable, TypeRep (..))
 import GHC.Fingerprint.Type(Fingerprint(..))
 #elif __GLASGOW_HASKELL__ >= 606
-import Data.Typeable (typeRepKey)
+import Data.Typeable (typeRepKey, Typeable, TypeRep)
 #endif
 
 #if __GLASGOW_HASKELL__ >= 703
@@ -267,11 +278,10 @@
 defaultLiftHashWithSalt :: (Hashable2 f, Hashable a) => (Int -> b -> Int) -> Int -> f a b -> Int
 defaultLiftHashWithSalt h = liftHashWithSalt2 hashWithSalt h
 
--- Since we support a generic implementation of 'hashWithSalt' we
+-- | Since we support a generic implementation of 'hashWithSalt' we
 -- cannot also provide a default implementation for that method for
 -- the non-generic instance use case. Instead we provide
 -- 'defaultHashWith'.
-
 defaultHashWithSalt :: Hashable a => Int -> a -> Int
 defaultHashWithSalt salt x = salt `combine` hash x
 
@@ -443,7 +453,7 @@
         | isIEEE x =
             assert (sizeOf x >= sizeOf (0::Word32) &&
                     alignment x >= alignment (0::Word32)) $
-            hash ((unsafePerformIO $ with x $ peek . castPtr) :: Word32)
+            hash ((unsafeDupablePerformIO $ with x $ peek . castPtr) :: Word32)
         | otherwise = hash (show x)
     hashWithSalt = defaultHashWithSalt
 
@@ -452,7 +462,7 @@
         | isIEEE x =
             assert (sizeOf x >= sizeOf (0::Word64) &&
                     alignment x >= alignment (0::Word64)) $
-            hash ((unsafePerformIO $ with x $ peek . castPtr) :: Word64)
+            hash ((unsafeDupablePerformIO $ with x $ peek . castPtr) :: Word64)
         | otherwise = hash (show x)
     hashWithSalt = defaultHashWithSalt
 
@@ -591,7 +601,7 @@
         step (SP s l) x   = SP (h s x) (l + 1)
 
 instance Hashable B.ByteString where
-    hashWithSalt salt bs = B.inlinePerformIO $
+    hashWithSalt salt bs = unsafeDupablePerformIO $
                            B.unsafeUseAsCStringLen bs $ \(p, len) ->
                            hashPtrWithSalt p (fromIntegral len) salt
 
@@ -641,6 +651,7 @@
     hash n = fromIntegral n
     hashWithSalt = defaultHashWithSalt
 
+#if __GLASGOW_HASKELL__ < 801
 -- | Compute the hash of a TypeRep, in various GHC versions we can do this quickly.
 hashTypeRep :: TypeRep -> Int
 {-# INLINE hashTypeRep #-}
@@ -651,7 +662,7 @@
 -- Fingerprint is just the MD5, so taking any Int from it is fine
 hashTypeRep (TypeRep (Fingerprint x _) _ _) = fromIntegral x
 #elif __GLASGOW_HASKELL__ >= 606
-hashTypeRep = B.inlinePerformIO . typeRepKey
+hashTypeRep = unsafeDupablePerformIO . typeRepKey
 #else
 hashTypeRep = hash . show
 #endif
@@ -661,6 +672,23 @@
     hashWithSalt = defaultHashWithSalt
     {-# INLINE hash #-}
 
+#else
+
+hashTypeRep :: Type.Reflection.TypeRep a -> Int
+hashTypeRep tr =
+    let Fingerprint x _ = typeRepFingerprint tr in fromIntegral x
+
+instance Hashable Type.Reflection.SomeTypeRep where
+    hash (Type.Reflection.SomeTypeRep r) = hashTypeRep r
+    hashWithSalt = defaultHashWithSalt
+    {-# INLINE hash #-}
+
+instance Hashable (Type.Reflection.TypeRep a) where
+    hash = hashTypeRep
+    hashWithSalt = defaultHashWithSalt
+    {-# INLINE hash #-}
+#endif
+
 #if MIN_VERSION_base(4,8,0)
 instance Hashable Void where
     hashWithSalt _ = absurd
@@ -854,6 +882,9 @@
 
 instance F.Foldable Hashed where
   foldr f acc (Hashed a _) = f a acc
+
+instance NFData a => NFData (Hashed a) where
+  rnf = rnf . unhashed
 
 -- | 'Hashed' cannot be 'Functor'
 mapHashed :: Hashable b => (a -> b) -> Hashed a -> Hashed b
diff --git a/Data/Hashable/Generic.hs b/Data/Hashable/Generic.hs
--- a/Data/Hashable/Generic.hs
+++ b/Data/Hashable/Generic.hs
@@ -22,7 +22,6 @@
 import Data.Hashable.Class
 import GHC.Generics
 
-
 -- Type without constructors
 instance GHashable arity V1 where
     ghashWithSalt _ salt _ = hashWithSalt salt ()
@@ -52,25 +51,64 @@
 instance (Hashable1 f, GHashable One g) => GHashable One (f :.: g) where
     ghashWithSalt targs salt = liftHashWithSalt (ghashWithSalt targs) salt . unComp1
 
-class GSum arity f where
-    hashSum :: HashArgs arity a -> Int -> Int -> Int -> f a -> Int
+class SumSize f => GSum arity f where
+    hashSum :: HashArgs arity a -> Int -> Int -> f a -> Int
+    -- hashSum args salt index value = ...
 
-instance (GSum arity a, GSum arity b, SumSize a, SumSize b) => GHashable arity (a :+: b) where
-    ghashWithSalt toHash salt = hashSum toHash salt 0 size
-        where size = unTagged (sumSize :: Tagged (a :+: b))
+-- [Note: Hashing a sum type]
+--
+-- The tree structure is used in GHC.Generics to represent the sum (and
+-- product) part of the generic represention of the type, e.g.:
+--
+--   (C0 ... :+: C1 ...) :+: (C2 ... :+: (C3 ... :+: C4 ...))
+--
+-- The value constructed with C2 constructor is represented as (R1 (L1 ...)).
+-- Yet, if we think that this tree is a flat (heterogenous) list:
+--
+--   [C0 ..., C1 ..., C2 ..., C3 ..., C4... ]
+--
+-- then the value constructed with C2 is a (dependent) pair (2, ...), and
+-- hashing it is simple:
+--
+--   salt `hashWithSalt` (2 :: Int) `hashWithSalt` ...
+--
+-- This is what we do below. When drilling down the tree, we count how many
+-- leafs are to the left (`index` variable). At the leaf case C1, we'll have an
+-- actual index into the sum.
+--
+-- This works well for balanced data. However for recursive types like:
+--
+--   data Nat = Z | S Nat
+--
+-- the `hashWithSalt salt (S (S (S Z)))` is
+--
+--   salt `hashWithSalt` (1 :: Int) -- first S
+--        `hashWithSalt` (1 :: Int) -- second S
+--        `hashWithSalt` (1 :: Int) -- third S
+--        `hashWithSalt` (0 :: Int) -- Z
+--        `hashWithSalt` ()         -- U1
+--
+-- For that type the manual implementation:
+--
+--    instance Hashable Nat where
+--        hashWithSalt salt n = hashWithSalt salt (natToInteger n)
+--
+-- would be better performing CPU and hash-quality wise (assuming that
+-- Integer's Hashable is of high quality).
+--
+instance (GSum arity a, GSum arity b) => GHashable arity (a :+: b) where
+    ghashWithSalt toHash salt = hashSum toHash salt 0
 
 instance (GSum arity a, GSum arity b) => GSum arity (a :+: b) where
-    hashSum toHash !salt !code !size s = case s of
-        L1 x -> hashSum toHash salt code           sizeL x
-        R1 x -> hashSum toHash salt (code + sizeL) sizeR x
+    hashSum toHash !salt !index s = case s of
+        L1 x -> hashSum toHash salt index x
+        R1 x -> hashSum toHash salt (index + sizeL) x
       where
-        sizeL = size `shiftR` 1
-        sizeR = size - sizeL
+        sizeL = unTagged (sumSize :: Tagged a)
     {-# INLINE hashSum #-}
 
 instance GHashable arity a => GSum arity (C1 c a) where
-    -- hashSum toHash !salt !code _ (M1 x) = ghashWithSalt toHash (hashWithSalt salt code) x
-    hashSum toHash !salt !code _ (M1 x) = hashWithSalt salt (ghashWithSalt toHash code x)
+    hashSum toHash !salt !index (M1 x) = ghashWithSalt toHash (hashWithSalt salt index) x
     {-# INLINE hashSum #-}
 
 class SumSize f where
diff --git a/hashable.cabal b/hashable.cabal
--- a/hashable.cabal
+++ b/hashable.cabal
@@ -1,5 +1,5 @@
 Name:                hashable
-Version:             1.2.5.0
+Version:             1.2.6.0
 Synopsis:            A class for types that can be converted to a hash value
 Description:         This package defines a class, 'Hashable', for types that
                      can be converted to a hash value.  This class
@@ -46,8 +46,9 @@
   Exposed-modules:   Data.Hashable
                      Data.Hashable.Lifted
   Other-modules:     Data.Hashable.Class
-  Build-depends:     base >= 4.0 && < 4.10,
-                     bytestring >= 0.9 && < 0.11
+  Build-depends:     base >= 4.0 && < 4.11,
+                     bytestring >= 0.9 && < 0.11,
+                     deepseq >= 1.3
   if impl(ghc)
     Build-depends:   ghc-prim,
                      text >= 0.11.0.5
diff --git a/tests/Regress.hs b/tests/Regress.hs
--- a/tests/Regress.hs
+++ b/tests/Regress.hs
@@ -1,15 +1,47 @@
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveGeneric #-}
 
 module Regress (regressions) where
 
 import qualified Test.Framework as F
+import Test.Framework.Providers.HUnit (testCase)
+import Test.HUnit ((@=?))
+import GHC.Generics (Generic)
+import Data.List (nub)
 
 #ifdef HAVE_MMAP
 import qualified Regress.Mmap as Mmap
 #endif
 
+import Data.Hashable
+
 regressions :: [F.Test]
-regressions = []
+regressions = [] ++
 #ifdef HAVE_MMAP
-              ++ Mmap.regressions
+    Mmap.regressions ++
 #endif
+    [ F.testGroup "Generic: sum of nullary constructors"
+        [ testCase "0" $ nullaryCase 0 S0
+        , testCase "1" $ nullaryCase 1 S1
+        , testCase "2" $ nullaryCase 2 S2
+        , testCase "3" $ nullaryCase 3 S3
+        , testCase "4" $ nullaryCase 4 S4
+        ]
+    , testCase "Generic: Peano https://github.com/tibbe/hashable/issues/135" $ do
+        let ns = take 20 $ iterate S Z
+        let hs = map hash ns
+        hs @=? nub hs
+    ]
+  where
+    nullaryCase :: Int -> SumOfNullary -> IO ()
+    nullaryCase n s = do
+        let salt = 42
+        let expected = salt `hashWithSalt` n `hashWithSalt` ()
+        let actual = hashWithSalt salt s
+        expected @=? actual
+
+data SumOfNullary = S0 | S1 | S2 | S3 | S4 deriving (Generic)
+instance Hashable SumOfNullary
+
+data Nat = Z | S Nat deriving (Generic)
+instance Hashable Nat
