diff --git a/Data/Chimera.hs b/Data/Chimera.hs
--- a/Data/Chimera.hs
+++ b/Data/Chimera.hs
@@ -8,8 +8,6 @@
 
 {-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE CPP                   #-}
-{-# LANGUAGE DeriveFoldable        #-}
-{-# LANGUAGE DeriveFunctor         #-}
 {-# LANGUAGE DeriveTraversable     #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
@@ -31,6 +29,7 @@
   -- * Construction
   , tabulate
   , tabulateFix
+  , tabulateFix'
   , iterate
   , cycle
 
@@ -60,11 +59,15 @@
 import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Unboxed as U
 
-#if DefineRepresentable
-import Control.Monad.Reader
+#ifdef MIN_VERSION_mtl
+import Control.Monad.Reader (MonadReader, ask, local)
+#endif
+#ifdef MIN_VERSION_distributive
 import Data.Distributive
+#ifdef MIN_VERSION_adjunctions
 import qualified Data.Functor.Rep as Rep
 #endif
+#endif
 
 import Data.Chimera.Compat
 import Data.Chimera.FromIntegral
@@ -145,22 +148,24 @@
   mzip as bs = tabulate (\w -> (index as w, index bs w))
   mzipWith f as bs = tabulate $ \w -> f (index as w) (index bs w)
 
-#if DefineRepresentable
-
+#ifdef MIN_VERSION_mtl
 instance MonadReader Word (Chimera V.Vector) where
-  ask = Rep.askRep
-  local = Rep.localRep
+  ask = tabulate id
+  local = flip $ (tabulate .) . (.) . index
+#endif
 
+#ifdef MIN_VERSION_distributive
 instance Distributive (Chimera V.Vector) where
-  distribute = Rep.distributeRep
-  collect = Rep.collectRep
+  distribute = tabulate . flip (fmap . flip index)
+  collect f = tabulate . flip ((<$>) . (. f) . flip index)
 
+#ifdef MIN_VERSION_adjunctions
 instance Rep.Representable (Chimera V.Vector) where
   type Rep (Chimera V.Vector) = Word
   tabulate = tabulate
   index = index
-
 #endif
+#endif
 
 bits :: Int
 bits = fbs (0 :: Word)
@@ -212,9 +217,35 @@
 -- 4862
 -- >>> take 10 (toList ch)
 -- [1,1,2,5,14,42,132,429,1430,4862]
+--
+-- __Note__: Only recursive function calls with decreasing arguments are memoized.
+-- If full memoization is desired, use 'tabulateFix'' instead.
 tabulateFix :: G.Vector v a => ((Word -> a) -> Word -> a) -> Chimera v a
 tabulateFix uf = runIdentity $ tabulateFixM ((pure .) . uf . (runIdentity .))
 
+-- | Fully memoizing version of 'tabulateFix'.
+-- This function will tabulate every recursive call,
+-- but might allocate a lot of memory in doing so.
+-- For example, the following piece of code calculates the
+-- highest number reached by the
+-- <https://en.wikipedia.org/wiki/Collatz_conjecture#Statement_of_the_problem Collatz sequence>
+-- of a given number, but also allocates tens of gigabytes of memory,
+-- because the Collatz sequence will spike to very high numbers.
+--
+-- >>> collatzF :: (Word -> Word) -> (Word -> Word)
+-- >>> collatzF _ 0 = 0
+-- >>> collatzF f n = if n <= 2 then 4 else n `max` f (if even n then n `quot` 2 else 3 * n + 1)
+-- >>>
+-- >>> maximumBy (comparing $ index $ tabulateFix' collatzF) [0..1000000]
+-- ...
+--
+-- Using 'memoizeFix' instead fixes the problem:
+--
+-- >>> maximumBy (comparing $ memoizeFix collatzF) [0..1000000]
+-- 56991483520
+tabulateFix' :: G.Vector v a => ((Word -> a) -> Word -> a) -> Chimera v a
+tabulateFix' uf = runIdentity $ tabulateFixM' ((pure .) . uf . (runIdentity .))
+
 -- | Monadic version of 'tabulateFix'.
 -- There are no particular guarantees about the order of recursive calls:
 -- they may be executed more than once or executed in different order.
@@ -224,13 +255,37 @@
      (Monad m, G.Vector v a)
   => ((Word -> m a) -> Word -> m a)
   -> m (Chimera v a)
-tabulateFixM f = result
+tabulateFixM = tabulateFixM_ Downwards
+
+{-# SPECIALIZE tabulateFixM :: G.Vector v a => ((Word -> Identity a) -> Word -> Identity a) -> Identity (Chimera v a) #-}
+
+-- | Monadic version of 'tabulateFix''.
+tabulateFixM'
+  :: forall m v a.
+     (Monad m, G.Vector v a)
+  => ((Word -> m a) -> Word -> m a)
+  -> m (Chimera v a)
+tabulateFixM' = tabulateFixM_ Full
+
+-- | Memoization strategy, only used by 'tabulateFixM_'.
+data Strategy = Full | Downwards
+
+-- | Internal implementation for 'tabulateFixM' and 'tabulateFixM''.
+tabulateFixM_
+  :: forall m v a.
+     (Monad m, G.Vector v a)
+  => Strategy
+  -> ((Word -> m a) -> Word -> m a)
+  -> m (Chimera v a)
+tabulateFixM_ strat f = result
   where
     result :: m (Chimera v a)
     result = Chimera <$> V.generateM (bits + 1) tabulateSubVector
 
     tabulateSubVector :: Int -> m (v a)
-    tabulateSubVector 0 = G.singleton <$> fix f 0
+    tabulateSubVector 0 = G.singleton <$> case strat of
+      Downwards -> fix f 0
+      Full      -> f (\k -> flip index k <$> result) 0
     tabulateSubVector i = subResult
       where
         subResult      = G.generateM ii (\j -> f fixF (int2word (ii + j)))
@@ -241,12 +296,12 @@
         fixF k
           | k < int2word ii
           = flip index k <$> result
-          | k < int2word ii `shiftL` 1
+          | k <= int2word ii `shiftL` 1 - 1
           = (`V.unsafeIndex` (word2int k - ii)) <$> subResultBoxed
           | otherwise
-          = f fixF k
-
-{-# SPECIALIZE tabulateFixM :: G.Vector v a => ((Word -> Identity a) -> Word -> Identity a) -> Identity (Chimera v a) #-}
+          = case strat of
+              Downwards -> f fixF k
+              Full      -> flip index k <$> result
 
 -- | 'iterate' @f@ @x@ returns an infinite stream
 -- of repeated applications of @f@ to @x@.
@@ -281,7 +336,7 @@
 index (Chimera vs) i =
   (vs `V.unsafeIndex` (fbs i - lz))
   `G.unsafeIndex`
-  (word2int (i .&. complement ((1 `shiftL` (fbs i - 1)) `unsafeShiftR` lz)))
+  word2int (i .&. complement ((1 `shiftL` (fbs i - 1)) `unsafeShiftR` lz))
   where
     lz :: Int
     !lz = word2int (clz i)
@@ -313,6 +368,8 @@
 -- would compute @f@ @n@ only once
 -- and cache the result in 'VChimera'.
 -- This is just a shortcut for 'index' '.' 'tabulate'.
+-- When @a@ is 'U.Unbox', it is faster to use
+-- 'index' ('tabulate' @f@ :: 'UChimera' @a@).
 --
 -- prop> memoize f n = f n
 memoize :: (Word -> a) -> (Word -> a)
@@ -321,18 +378,20 @@
 -- | For a given @f@ memoize a recursive function 'fix' @f@,
 -- caching results in 'VChimera'.
 -- This is just a shortcut for 'index' '.' 'tabulateFix'.
+-- When @a@ is 'U.Unbox', it is faster to use
+-- 'index' ('tabulateFix' @f@ :: 'UChimera' @a@).
 --
 -- prop> memoizeFix f n = fix f n
 --
 -- For example, imagine that we want to memoize
 -- <https://en.wikipedia.org/wiki/Fibonacci_number Fibonacci numbers>:
 --
--- >>> fibo n = if n < 2 then fromIntegral n else fibo (n - 1) + fibo (n - 2)
+-- >>> fibo n = if n < 2 then toInteger n else fibo (n - 1) + fibo (n - 2)
 --
 -- Can we find @fiboF@ such that @fibo@ = 'fix' @fiboF@?
 -- Just replace all recursive calls to @fibo@ with @f@:
 --
--- >>> fiboF f n = if n < 2 then fromIntegral n else f (n - 1) + f (n - 2)
+-- >>> fiboF f n = if n < 2 then toInteger n else f (n - 1) + f (n - 2)
 --
 -- Now we are ready to use 'memoizeFix':
 --
@@ -340,6 +399,17 @@
 -- 55
 -- >>> memoizeFix fiboF 100
 -- 354224848179261915075
+--
+-- This function can be used even when arguments
+-- of recursive calls are not strictly decreasing,
+-- but they might not get memoized. If this is not desired
+-- use 'tabulateFix'' instead.
+-- For example, here is a routine to measure the length of
+-- <https://oeis.org/A006577 Collatz sequence>:
+--
+-- >>> collatzF f n = if n <= 1 then 0 else 1 + f (if even n then n `quot` 2 else 3 * n + 1)
+-- >>> memoizeFix collatzF 27
+-- 111
 memoizeFix :: ((Word -> a) -> Word -> a) -> (Word -> a)
 memoizeFix = index @V.Vector . tabulateFix
 
diff --git a/Data/Chimera/WheelMapping.hs b/Data/Chimera/WheelMapping.hs
--- a/Data/Chimera/WheelMapping.hs
+++ b/Data/Chimera/WheelMapping.hs
@@ -66,6 +66,7 @@
 --
 
 {-# LANGUAGE BangPatterns  #-}
+{-# LANGUAGE CPP           #-}
 {-# LANGUAGE MagicHash     #-}
 {-# LANGUAGE UnboxedTuples #-}
 
@@ -162,7 +163,7 @@
 --
 -- prop> toWheel210 . fromWheel210 == id
 toWheel210 :: Word -> Word
-toWheel210 i@(W# i#) = q `shiftL` 5 + q `shiftL` 4 + W# (indexWord8OffAddr# table# (word2Int# r#))
+toWheel210 i@(W# i#) = q `shiftL` 5 + q `shiftL` 4 + W# tableEl#
   where
     !(q, W# r#) = case bits of
       64 -> (q64, r64)
@@ -173,6 +174,12 @@
     q64 = W# z1# `shiftR` 6
     r64 = i - q64 * 210
 
+    tableEl# =
+#if MIN_VERSION_base(4,16,0)
+      word8ToWord#
+#endif
+      (indexWord8OffAddr# table# (word2Int# r#))
+
     table# :: Addr#
     table# = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\SOH\SOH\STX\STX\STX\STX\ETX\ETX\EOT\EOT\EOT\EOT\ENQ\ENQ\ENQ\ENQ\ENQ\ENQ\ACK\ACK\a\a\a\a\a\a\b\b\b\b\t\t\n\n\n\n\v\v\v\v\v\v\f\f\f\f\f\f\r\r\SO\SO\SO\SO\SO\SO\SI\SI\SI\SI\DLE\DLE\DC1\DC1\DC1\DC1\DC1\DC1\DC2\DC2\DC2\DC2\DC3\DC3\DC3\DC3\DC3\DC3\DC4\DC4\DC4\DC4\DC4\DC4\DC4\DC4\NAK\NAK\NAK\NAK\SYN\SYN\ETB\ETB\ETB\ETB\CAN\CAN\EM\EM\EM\EM\SUB\SUB\SUB\SUB\SUB\SUB\SUB\SUB\ESC\ESC\ESC\ESC\ESC\ESC\FS\FS\FS\FS\GS\GS\GS\GS\GS\GS\RS\RS\US\US\US\US      !!\"\"\"\"\"\"######$$$$%%&&&&''''''(())))))****++,,,,--........../"#
     -- map Data.Char.chr [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 23, 23, 23, 23, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47]
@@ -187,7 +194,7 @@
 -- >>> map fromWheel210 [0..9]
 -- [1,11,13,17,19,23,29,31,37,41]
 fromWheel210 :: Word -> Word
-fromWheel210 i@(W# i#) = q * 210 + W# (indexWord8OffAddr# table# (word2Int# r#))
+fromWheel210 i@(W# i#) = q * 210 + W# tableEl#
   where
     !(q, W# r#) = case bits of
       64 -> (q64, r64)
@@ -197,6 +204,12 @@
     !(# z1#, _ #) = timesWord2# m# i#
     q64 = W# z1# `shiftR` 5
     r64 = i - q64 `shiftL` 5 - q64 `shiftL` 4
+
+    tableEl# =
+#if MIN_VERSION_base(4,16,0)
+      word8ToWord#
+#endif
+      (indexWord8OffAddr# table# (word2Int# r#))
 
     table# :: Addr#
     table# = "\SOH\v\r\DC1\DC3\ETB\GS\US%)+/5;=CGIOSYaegkmqy\DEL\131\137\139\143\149\151\157\163\167\169\173\179\181\187\191\193\197\199\209"#
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
-# chimera
+# chimera [![Hackage](http://img.shields.io/hackage/v/chimera.svg)](https://hackage.haskell.org/package/chimera) [![Stackage LTS](http://stackage.org/package/chimera/badge/lts)](http://stackage.org/lts/package/chimera) [![Stackage Nightly](http://stackage.org/package/chimera/badge/nightly)](http://stackage.org/nightly/package/chimera)
 
 Lazy infinite compact streams with cache-friendly O(1) indexing
 and applications for memoization.
 
-----
+## Introduction
 
 Imagine having a function `f :: Word -> a`,
 which is expensive to evaluate. We would like to _memoize_ it,
@@ -96,6 +96,75 @@
 isPrime' = memoizeFix isPrimeF
 ```
 
+## Example 3
+
+No manual on memoization is complete
+without Fibonacci numbers:
+
+```haskell
+fibo :: Word -> Integer
+fibo = memoizeFix $ \f n -> if n < 2 then toInteger n else f (n - 1) + f (n - 2)
+```
+
+No cleverness involved: just write a recursive function
+and let `memoizeFix` take care about everything else:
+
+```haskell
+> fibo 100
+354224848179261915075
+```
+
+## What about non-`Word` arguments?
+
+`Chimera` itself can memoize only `Word -> a` functions, which sounds restrictive.
+That is because we decided to outsource
+enumerating of user's datatypes to other packages, e. g.,
+[`cantor-pairing`](http://hackage.haskell.org/package/cantor-pairing).
+Use `fromInteger . fromCantor` to convert data to `Word`
+and `toCantor . toInteger` to go back.
+
+Also, `Data.Chimera.ContinuousMapping` covers several simple cases,
+such as `Int`, pairs and triples.
+
+## Benchmarks
+
+How important is to store cached data as a flat array instead of a lazy binary tree?
+Let us measure the maximal length of [Collatz sequence](https://oeis.org/A006577),
+using `chimera` and `memoize` packages.
+
+```haskell
+{-# LANGUAGE TypeApplications #-}
+import Data.Chimera
+import Data.Function.Memoize
+import Data.Ord
+import Data.List
+import Data.Time.Clock
+
+collatzF :: Integral a => (a -> a) -> (a -> a)
+collatzF f n = if n <= 1 then 0 else 1 + f (if even n then n `quot` 2 else 3 * n + 1)
+
+measure :: (Integral a, Show a) => String -> (((a -> a) -> (a -> a)) -> (a -> a)) -> IO ()
+measure name memo = do
+  t0 <- getCurrentTime
+  print $ maximumBy (comparing (memo collatzF)) [0..1000000]
+  t1 <- getCurrentTime
+  putStrLn $ name ++ " " ++ show (diffUTCTime t1 t0)
+
+main :: IO ()
+main = do
+  measure "chimera" Data.Chimera.memoizeFix
+  measure "memoize" (Data.Function.Memoize.memoFix @Int)
+```
+
+Here `chimera` appears to be 20x faster than `memoize`:
+
+```
+837799
+chimera 0.428015s
+837799
+memoize 8.955953s
+```
+
 ## Magic and its exposure
 
 Internally `Chimera` is represented as a _boxed_ vector
@@ -106,9 +175,9 @@
 ```
 
 Assuming 64-bit architecture, the outer vector consists of 65 inner vectors
-of sizes 1, 1, 2, 2<sup>2</sup>, ..., 2<sup>63</sup>. Since the outer vector
+of sizes 1, 1, 2, 2², ..., 2⁶³. Since the outer vector
 is boxed, inner vectors are allocated on-demand only: quite fortunately,
-there is no need to allocate all 2<sup>64</sup> elements at once.
+there is no need to allocate all 2⁶⁴ elements at once.
 
 To access an element by its index it is enough to find out to which inner
 vector it belongs, which, thanks to the doubling pattern of sizes,
@@ -120,15 +189,19 @@
 over a thin set of indices.
 
 One can argue that this structure is not infinite,
-because it cannot handle more than 2<sup>64</sup> elements.
+because it cannot handle more than 2⁶⁴ elements.
 I believe that it is _infinite enough_ and no one would be able to exhaust
 its finiteness any time soon. Strictly speaking, to cope with indices out of
 `Word` range and `memoize`
 [Ackermann function](https://en.wikipedia.org/wiki/Ackermann_function),
 one could use more layers of indirection, raising access time
-to O([log<sup>*</sup>](https://en.wikipedia.org/wiki/Iterated_logarithm) n).
+to O([log ⃰](https://en.wikipedia.org/wiki/Iterated_logarithm) n).
 I still think that it is morally correct to claim O(1) access,
 because all asymptotic estimates of data structures
 are usually made under an assumption that they contain
 less than `maxBound :: Word` elements
 (otherwise you can not even treat pointers as a fixed-size data).
+
+## Additional resources
+
+* [Lazy streams with O(1) access](https://github.com/Bodigrim/my-talks/raw/master/londonhaskell2020/slides.pdf), London Haskell, 25.02.2020.
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -1,14 +1,26 @@
+{-# LANGUAGE CPP #-}
+
 module Main where
 
-import Control.Monad.State
+import Control.Monad.State (evalState, put, get)
 import Data.Chimera
-import Gauge.Main
+import Test.Tasty.Bench
 import System.Random
 
+#ifdef MIN_VERSION_ral
+import qualified Data.RAList as RAL
+#endif
+
+sizes :: Num a => [a]
+sizes = [100, 200, 500, 1000]
+
 main :: IO ()
-main = defaultMain
-  [ bgroup "read/Chimera" (map benchReadChimera [100, 200, 500, 1000])
-  , bgroup "read/List"    (map benchReadList    [100, 200, 500, 1000])
+main = defaultMain $ (: []) $ bgroup "read"
+  [ bgroup "Chimera" (map benchReadChimera sizes)
+  , bgroup "List"    (map benchReadList    sizes)
+#ifdef MIN_VERSION_ral
+  , bgroup "RAL"     (map benchReadRAL     sizes)
+#endif
   ]
 
 randomChimera :: UChimera Int
@@ -21,6 +33,11 @@
 randomList :: [Int]
 randomList = randoms (mkStdGen 42)
 
+#ifdef MIN_VERSION_ral
+randomRAL :: RAL.RAList Int
+randomRAL = RAL.fromList $ take (maximum sizes) $ randoms (mkStdGen 42)
+#endif
+
 randomIndicesWord :: [Word]
 randomIndicesWord = randoms (mkStdGen 42)
 
@@ -36,7 +53,18 @@
 
 benchReadList :: Int -> Benchmark
 benchReadList n
-  = bench (show n)
+  = bcompare ("$NF == \"" ++ show n ++ "\" && $(NF-1) == \"Chimera\"")
+  $ bench (show n)
   $ nf (sum . map (randomList !!))
   $ map (`mod` n)
   $ take n randomIndicesInt
+
+#ifdef MIN_VERSION_ral
+benchReadRAL :: Int -> Benchmark
+benchReadRAL n
+  = bcompare ("$NF == \"" ++ show n ++ "\" && $(NF-1) == \"Chimera\"")
+  $ bench (show n)
+  $ nf (sum . map (randomRAL RAL.!))
+  $ map (`mod` n)
+  $ take n randomIndicesInt
+#endif
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,38 @@
+# 0.3.2.0
+
+* Implement `tabulateFix'`.
+* Compatibility fixes.
+
+# 0.3.1.0
+
+* Define `Monad`, `MonadFix`, `MonadZip` instances.
+* Define `Distributive` and `Representable` instances.
+* Speed up `index`.
+
+# 0.3.0.0
+
+* Make `Chimera` polymorphic by vector type
+* Implement `memoize` and `memoizeFix`.
+* Implement `cycle` and `iterate`.
+* Implement `mapSubvectors` and `zipSubvectors`
+* Make boxed `tabulateFix` even lazier.
+* Speed up `Data.Chimera.WheelMapping`.
+
+# 0.2.0.0
+
+* Generalize bit streams to `Chimera` datatype.
+* Define `Applicative` instance.
+* Implement `toList`, `trueIndices` and `falseIndices`.
+* Make boxed `tabulateFix` lazier.
+
+# 0.1.0.2
+
+* Compatibility fixes.
+
+# 0.1.0.1
+
+* Compatibility fixes.
+
+# 0.1.0.0
+
+* Initial release.
diff --git a/chimera.cabal b/chimera.cabal
--- a/chimera.cabal
+++ b/chimera.cabal
@@ -1,6 +1,6 @@
 name: chimera
-version: 0.3.1.0
-cabal-version: >=1.10
+version: 0.3.2.0
+cabal-version: 2.0
 build-type: Simple
 license: BSD3
 license-file: LICENSE
@@ -8,11 +8,12 @@
 maintainer: andrew.lelechenko@gmail.com
 homepage: https://github.com/Bodigrim/chimera#readme
 category: Data
-synopsis: Lazy infinite streams with O(1) indexing
+synopsis: Lazy infinite streams with O(1) indexing and applications for memoization
 author: Bodigrim
 extra-source-files:
   README.md
-tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2
+  changelog.md
+tested-with: GHC==9.0.1, GHC==8.10.5, GHC==8.8.4, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2
 description:
   There are plenty of memoizing libraries on Hackage, but they
   usually fall into two categories:
@@ -51,7 +52,6 @@
   build-depends: base >=4.9 && <5, vector
   if flag(representable)
     build-depends: adjunctions, distributive, mtl
-    cpp-options: -DDefineRepresentable
   exposed-modules:
     Data.Chimera
     Data.Chimera.ContinuousMapping
@@ -60,9 +60,9 @@
     Data.Chimera.Compat
     Data.Chimera.FromIntegral
   default-language: Haskell2010
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat
 
-test-suite test
+test-suite chimera-test
   build-depends:
     base >=4.5 && <5,
     chimera,
@@ -76,17 +76,17 @@
   main-is: Test.hs
   default-language: Haskell2010
   hs-source-dirs: test
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat
 
-benchmark bench
+benchmark chimera-bench
   build-depends:
     base,
     chimera,
-    gauge,
     mtl,
-    random
+    random,
+    tasty-bench >= 0.2.4
   type: exitcode-stdio-1.0
   main-is: Bench.hs
   default-language: Haskell2010
   hs-source-dirs: bench
-  ghc-options: -Wall
+  ghc-options: -Wall -Wcompat
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -10,8 +10,8 @@
 import Test.Tasty.QuickCheck as QC
 
 import Data.Bits
+import Data.Foldable
 import Data.Function (fix)
-import Data.List
 import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Unboxed as U
 
@@ -43,7 +43,7 @@
     ]
 
   , testGroup "to . from Z-curve 2D"
-    [ QC.testProperty "random" $ \z -> (\(x, y) -> toZCurve x y) (fromZCurve z) === z
+    [ QC.testProperty "random" $ \z -> uncurry toZCurve (fromZCurve z) === z
     ]
   , testGroup "from . to Z-curve 2D"
     [ QC.testProperty "random" $ \x y -> fromZCurve (toZCurve x y) === (x `rem` (1 `shiftL` 32), y `rem` (1 `shiftL` 32))
@@ -73,11 +73,18 @@
     \(Fun _ (f :: Word -> Bool)) ix ->
       let jx = ix `mod` 65536 in
         f jx === Ch.index (Ch.tabulate f :: Ch.Chimera U.Vector Bool) jx
+
   , QC.testProperty "index . tabulateFix = fix" $
     \(Fun _ g) ix ->
       let jx = ix `mod` 65536 in
         let f = mkUnfix g in
           fix f jx === Ch.index (Ch.tabulateFix f :: Ch.Chimera U.Vector Bool) jx
+
+  , QC.testProperty "index . tabulateFix' = fix" $
+    \(Fun _ g) ix ->
+      let jx = ix `mod` 65536 in
+        let f = mkUnfix g in
+          fix f jx === Ch.index (Ch.tabulateFix' f :: Ch.Chimera U.Vector Bool) jx
 
   , QC.testProperty "iterate" $
     \(Fun _ (f :: Word -> Word)) seed ix ->
