diff --git a/Data/ByteArray/ScrubbedBytes.hs b/Data/ByteArray/ScrubbedBytes.hs
--- a/Data/ByteArray/ScrubbedBytes.hs
+++ b/Data/ByteArray/ScrubbedBytes.hs
@@ -64,10 +64,29 @@
     | otherwise               = IO $ \s ->
         case newAlignedPinnedByteArray# sz 8# s of
             (# s1, mbarr #) ->
-                let !scrubber = getScrubber sz
+                let !scrubber = (getScrubber sz) (byteArrayContents# (unsafeCoerce# mbarr))
                     !mba      = ScrubbedBytes mbarr
-                 in case mkWeak# mbarr () (scrubber (byteArrayContents# (unsafeCoerce# mbarr)) >> touchScrubbedBytes mba) s1 of
+                 in case mkWeak# mbarr () (finalize scrubber mba) s1 of
                     (# s2, _ #) -> (# s2, mba #)
+  where
+#if __GLASGOW_HASKELL__ > 800
+    finalize :: (State# RealWorld -> State# RealWorld) -> ScrubbedBytes -> State# RealWorld -> State# RealWorld
+    finalize scrubber mba@(ScrubbedBytes _) = \s1 ->
+        case scrubber s1 of
+            s2 -> touch# mba s2
+#elif __GLASGOW_HASKELL__ >= 800
+    finalize :: (State# RealWorld -> State# RealWorld) -> ScrubbedBytes -> State# RealWorld -> (# State# RealWorld, () #)
+    finalize scrubber mba@(ScrubbedBytes _) = \s1 ->
+        case scrubber s1 of
+            s2 -> case touch# mba s2 of
+                    s3 -> (# s3, () #)
+#else
+    finalize :: (State# RealWorld -> State# RealWorld) -> ScrubbedBytes -> IO ()
+    finalize scrubber mba@(ScrubbedBytes _) = IO $ \s1 -> do
+        case scrubber s1 of
+            s2 -> case touch# mba s2 of
+                    s3 -> (# s3, () #)
+#endif
 
 scrubbedBytesAllocRet :: Int -> (Ptr p -> IO a) -> IO (a, ScrubbedBytes)
 scrubbedBytesAllocRet sz f = do
diff --git a/Data/Memory/Internal/CompatPrim.hs b/Data/Memory/Internal/CompatPrim.hs
--- a/Data/Memory/Internal/CompatPrim.hs
+++ b/Data/Memory/Internal/CompatPrim.hs
@@ -75,10 +75,10 @@
                  -> (Int# -> a) -- ^ if it divided by 8, the argument is the number of 8 bytes words
                  -> (Int# -> a) -- ^ if it doesn't, just the number of bytes
                  -> a
-#if __GLASGOW_HASKELL__ >= 740
+#if __GLASGOW_HASKELL__ > 704
 eitherDivideBy8# v f8 f1 =
-    let !(# q, r #) = quotRemInt v 8#
-     in if booleanPrim (r ==# 0)
+    let !(# q, r #) = quotRemInt# v 8#
+     in if booleanPrim (r ==# 0#)
             then f8 q
             else f1 v
 #else
diff --git a/Data/Memory/Internal/Scrubber.hs b/Data/Memory/Internal/Scrubber.hs
--- a/Data/Memory/Internal/Scrubber.hs
+++ b/Data/Memory/Internal/Scrubber.hs
@@ -15,10 +15,9 @@
     ) where
 
 import GHC.Prim
-import GHC.IO
 import Data.Memory.Internal.CompatPrim (booleanPrim)
 
-getScrubber :: Int# -> (Addr# -> IO ())
+getScrubber :: Int# -> (Addr# -> State# RealWorld -> State# RealWorld)
 getScrubber sz 
     | booleanPrim (sz ==# 4#)  = scrub4
     | booleanPrim (sz ==# 8#)  = scrub8
@@ -26,31 +25,31 @@
     | booleanPrim (sz ==# 32#) = scrub32
     | otherwise                = scrubBytes sz
   where
-        scrub4 a = IO $ \s -> (# writeWord32OffAddr# a 0# 0## s, () #)
+        scrub4 a = \s -> writeWord32OffAddr# a 0# 0## s
 #if WORD_SIZE_IN_BITS == 64
-        scrub8 a = IO $ \s -> (# writeWord64OffAddr# a 0# 0## s, () #)
-        scrub16 a = IO $ \s1 ->
+        scrub8 a = \s -> writeWord64OffAddr# a 0# 0## s
+        scrub16 a = \s1 ->
             let !s2 = writeWord64OffAddr# a 0# 0## s1
                 !s3 = writeWord64OffAddr# a 1# 0## s2
-             in (# s3, () #)
-        scrub32 a = IO $ \s1 ->
+             in s3
+        scrub32 a = \s1 ->
             let !s2 = writeWord64OffAddr# a 0# 0## s1
                 !s3 = writeWord64OffAddr# a 1# 0## s2
                 !s4 = writeWord64OffAddr# a 2# 0## s3
                 !s5 = writeWord64OffAddr# a 3# 0## s4
-             in (# s5, () #)
+             in s5
 #else
-        scrub8 a = IO $ \s1 ->
+        scrub8 a = \s1 ->
             let !s2 = writeWord32OffAddr# a 0# 0## s1
                 !s3 = writeWord32OffAddr# a 1# 0## s2
-             in (# s3, () #)
-        scrub16 a = IO $ \s1 ->
+             in s3
+        scrub16 a = \s1 ->
             let !s2 = writeWord32OffAddr# a 0# 0## s1
                 !s3 = writeWord32OffAddr# a 1# 0## s2
                 !s4 = writeWord32OffAddr# a 2# 0## s3
                 !s5 = writeWord32OffAddr# a 3# 0## s4
-             in (# s5, () #)
-        scrub32 a = IO $ \s1 ->
+             in s5
+        scrub32 a = \s1 ->
             let !s2 = writeWord32OffAddr# a 0# 0## s1
                 !s3 = writeWord32OffAddr# a 1# 0## s2
                 !s4 = writeWord32OffAddr# a 2# 0## s3
@@ -59,11 +58,11 @@
                 !s7 = writeWord32OffAddr# a 5# 0## s6
                 !s8 = writeWord32OffAddr# a 6# 0## s7
                 !s9 = writeWord32OffAddr# a 7# 0## s8
-             in (# s9, () #)
+             in s9
 #endif
 
-scrubBytes :: Int# -> Addr# -> IO ()
-scrubBytes sz8 addr = IO $ \s -> (# loop sz8 addr s, () #)
+scrubBytes :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
+scrubBytes sz8 addr = \s -> loop sz8 addr s
   where loop :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
         loop n a s
             | booleanPrim (n ==# 0#) = s
diff --git a/memory.cabal b/memory.cabal
--- a/memory.cabal
+++ b/memory.cabal
@@ -1,5 +1,5 @@
 Name:                memory
-Version:             0.10
+Version:             0.11
 Synopsis:            memory and related abstraction stuff
 Description:
     Chunk of memory, polymorphic byte array management and manipulation
@@ -13,6 +13,8 @@
     * Aliasing with endianness support.
     .
     * Encoding : Base16, Base32, Base64.
+    .
+    * Hashing : FNV, SipHash
 License:             BSD3
 License-file:        LICENSE
 Copyright:           Vincent Hanquez <vincent@snarc.org>
