diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+.cabal-sandbox
+cabal.sandbox.config
+.stack-work
+idx/
+dist/
+log/
+*.swp
+*.swo
+*.swn
+*.swm
+*.o
+*.hi
+*.dyn_hi
+*.dyn_o
+TAGS
+tags
+test/main
+test/text
+bench/tiers
+eg/test-text
+doc/*.html
+doc/*.css
+doc/*.js
+doc/*.png
+doc/*.gif
+doc/*.json
+mk/toplibs
+README.html
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,81 @@
+# .travis.yml file for leancheck-instances
+#
+# Copyright:   (c) 2017-2018 Rudy Matela
+# License:     3-Clause BSD  (see the file LICENSE)
+# Maintainer:  Rudy Matela <rudy@matela.com.br>
+
+language: c  # not really
+
+notifications:
+  email:
+    on_failure: change
+
+sudo: false
+
+cache:
+  directories:
+  - $HOME/.ghc
+  - $HOME/.cabal
+  - $HOME/.stack
+
+before_install:
+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
+- ghc --version
+- cabal --version
+- haddock --version
+- rm -f ~/.cabal/config && cabal update
+# Download and unpack the stack executable
+# "Once Travis whitelists the stack.dev files," simply include stack in the
+# addons section. -- https://docs.haskellstack.org/en/stable/travis_ci/
+- mkdir -p ~/.local/bin
+- export PATH=$HOME/.local/bin:$PATH
+- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
+- stack config set system-ghc --global true
+- stack --version
+- cabal install leancheck bytestring nats text
+
+script:
+- make && make test
+- make haddock
+- make test-sdist
+- cabal test --ghc-option=-O0
+- stack $STACKR --no-terminal --skip-ghc-check test --ghc-options=-O0
+
+matrix:
+  allow_failures:
+  - ghc: 'head'
+  include:
+  - ghc: 'head'
+    env:                   GHCVER=head         CABALVER=head
+    addons: {apt: {packages: [ghc-head,   cabal-install-head], sources: hvr-ghc}}
+  - ghc: '8.6'
+    env:                   GHCVER=8.6.1        CABALVER=2.4
+    addons: {apt: {packages: [ghc-8.6.1,  cabal-install-2.4],  sources: hvr-ghc}}
+  - ghc: '8.4'
+    env:                   GHCVER=8.4.4        CABALVER=2.2
+    addons: {apt: {packages: [ghc-8.4.4,  cabal-install-2.2],  sources: hvr-ghc}}
+  - ghc: '8.2'
+    env:                   GHCVER=8.2.2        CABALVER=2.0
+    addons: {apt: {packages: [ghc-8.2.2,  cabal-install-2.0],  sources: hvr-ghc}}
+  - ghc: '8.0'
+    env:                   GHCVER=8.0.2        CABALVER=1.24
+    addons: {apt: {packages: [ghc-8.0.2,  cabal-install-1.24], sources: hvr-ghc}}
+  - ghc: '7.10'
+    env:                   GHCVER=7.10.3       CABALVER=1.22   STACKR=--resolver=lts-11.11
+    addons: {apt: {packages: [ghc-7.10.3, cabal-install-1.22], sources: hvr-ghc}}
+  # we only support stack with GHC >= 7.10
+  - ghc: '7.8'
+    env:                   GHCVER=7.8.4        CABALVER=1.18
+    addons: {apt: {packages: [ghc-7.8.4,  cabal-install-1.18], sources: hvr-ghc}}
+    before_install:
+    - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
+    - ghc --version
+    - cabal --version
+    - haddock --version
+    - rm -f ~/.cabal/config && cabal update
+    - cabal install leancheck bytestring nats text
+    script:
+    - make && make test
+    - make haddock HADDOCKFLAGS=
+    - make test-sdist
+    - cabal test
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2018, Rudy Matela
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Rudy Matela nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,99 @@
+# Makefile for leancheck-instances
+#
+# Copyright:   (c) 2015-2018 Rudy Matela
+# License:     3-Clause BSD  (see the file LICENSE)
+# Maintainer:  Rudy Matela <rudy@matela.com.br>
+TESTS = test/main      \
+        test/text
+EGS = \
+	eg/test-text
+BENCHS = \
+	bench/tiers
+GHCIMPORTDIRS = src:test
+# -dynamic is needed only for src/Test/LeanCheck/Derive.hs and test/derive.hs
+GHCFLAGS = -O2 $(shell grep -q "Arch Linux" /etc/lsb-release && echo -dynamic)
+HADDOCKFLAGS = --no-print-missing-docs
+
+all: mk/toplibs
+
+all-all: mk/All.o
+
+test: $(patsubst %,%.run,$(TESTS)) diff-test test-sdist
+
+diff-test: diff-test-tiers $(patsubst %,%.diff-test,$(EGS))
+
+update-diff-test: update-diff-test-tiers $(patsubst %,%.update-diff-test,$(EGS))
+
+%.run: %
+	./$<
+
+eg/%.diff-test: eg/%
+	./$< | diff -rud test/diff/$<.out -
+
+eg/%.update-diff-test: eg/%
+	./$< >           test/diff/$<.out
+
+clean: clean-hi-o clean-haddock
+	rm -f $(TESTS) $(BENCHS) $(EGS) mk/toplibs
+
+full-clean: clean
+	rm -rf .stack-work
+	rm -f tags TAGS
+
+ghci: mk/All.ghci
+
+install:
+	@echo "use \`cabal install' instead"
+
+test-sdist:
+	./test/sdist
+
+test-via-cabal:
+	cabal test
+
+test-via-stack:
+	stack test
+
+legacy-test: # needs ghc-8.2 .. ghc-7.8 installed as such
+	make clean  &&  make test GHC=ghc-8.2  GHCFLAGS="-Werror -dynamic"
+	make clean  &&  make test GHC=ghc-8.0  GHCFLAGS="-Werror -dynamic"
+	make clean  &&  make test GHC=ghc-7.10 GHCFLAGS="-Werror -dynamic"
+	make clean  &&  make test GHC=ghc-7.8  GHCFLAGS="-Werror -dynamic"
+	make clean  &&  make test
+
+legacy-test-via-cabal: # needs similarly named cabal wrappers
+	cabal clean  &&  cabal-ghc-8.2  configure  &&  cabal-ghc-8.2  test
+	cabal clean  &&  cabal-ghc-8.0  configure  &&  cabal-ghc-8.0  test
+	cabal clean  &&  cabal-ghc-7.10 configure  &&  cabal-ghc-7.10 test
+	cabal clean  &&  cabal-ghc-7.8  configure  &&  cabal-ghc-7.8  test
+	cabal clean  &&  cabal test
+
+hlint:
+	hlint \
+	  --ignore "Use import/export shortcut" \
+	  --ignore "Redundant bracket" \
+	  .
+
+markdown:
+	pandoc README.md -o README.html
+	pandoc doc/tutorial.md -o doc/tutorial.html
+	pandoc doc/data-invariant.md -o doc/data-invariant.html
+
+# NOTE: (very hacky!) the following target allows parallel compilation (-jN) of
+# eg and tests programs so long as they don't share dependencies _not_ stored
+# in src/ and tests/.  Runnable binaries should depend on mk/toplibs instead of
+# actual Haskell source files
+mk/toplibs: mk/Toplibs.o
+	touch mk/toplibs
+
+include mk/haskell.mk
+
+diff-test-tiers: bench/tiers
+	./bench/tiers "Natural"          | diff -rud test/diff/tiers-Natural.out     -
+	./bench/tiers "Text"             | diff -rud test/diff/tiers-Text.out        -
+	./bench/tiers "ByteString" 6     | diff -rud test/diff/tiers-ByteString.out  -
+
+update-diff-test-tiers: bench/tiers
+	./bench/tiers "Natural"          > test/diff/tiers-Natural.out
+	./bench/tiers "Text"             > test/diff/tiers-Text.out
+	./bench/tiers "ByteString" 6     > test/diff/tiers-ByteString.out
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,69 @@
+LeanCheck
+=========
+
+[![leancheck-instances's Build Status][build-status]][build-log]
+[![leancheck-instances on Hackage][hackage-version]][leancheck-instances-on-hackage]
+[![leancheck-instances on Stackage LTS][stackage-lts-badge]][leancheck-instances-on-stackage-lts]
+[![leancheck-instances on Stackage Nightly][stackage-nightly-badge]][leancheck-instances-on-stackage-nightly]
+
+This package extends [LeanCheck] by providing [`Listable`] instances for common types provided by the
+Haskell Platform.
+
+This package is to [LeanCheck] what [quickcheck-instances] is to [QuickCheck].
+The current objective is to include all types supported by [quickcheck-instances].
+
+
+Installing
+----------
+
+To install the latest leancheck-instances version from Hackage, just run:
+
+	$ cabal update
+	$ cabal install leancheck-instances
+
+
+Examples
+--------
+
+TBA
+
+
+Further reading / see also
+--------------------------
+
+* [leancheck-instances' Haddock Documentation];
+* [LeanCheck];
+* [LeanCheck provider for Tasty]
+  -- `$ cabal install tasty-leancheck` ;
+* [LeanCheck provider for test-framework]
+  -- `$ cabal install test-framework-leancheck` ;
+* [LeanCheck provider for Hspec]
+  -- `$ cabal install hspec-leancheck` .
+
+
+[leancheck-instances' Haddock documentation]: https://hackage.haskell.org/package/leancheck-instances/docs/Test-LeanCheck-Instances.html
+[LeanCheck's Haddock documentation]: https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html
+
+[`Listable`]:       https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#t:Listable
+[`holds`]:          https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#v:holds
+[`counterExample`]: https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#v:counterExample
+[`check`]:          https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#v:check
+[`tiers`]:          https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#v:tiers
+[`list`]:           https://hackage.haskell.org/package/leancheck/docs/Test-LeanCheck.html#v:list
+
+[LeanCheck provider for Tasty]:          https://hackage.haskell.org/package/tasty-leancheck
+[LeanCheck provider for test-framework]: https://hackage.haskell.org/package/test-framework-leancheck
+[LeanCheck provider for Hspec]:          https://hackage.haskell.org/package/hspec-leancheck
+[LeanCheck]:                             https://github.com/rudymatela/leancheck
+[QuickCheck]:                            https://hackage.haskell.org/package/QuickCheck
+[quickcheck-instances]:                  https://hackage.haskell.org/package/quickcheck-instances
+
+[build-status]: https://travis-ci.org/rudymatela/leancheck-instances.svg?branch=master
+[build-log]:    https://travis-ci.org/rudymatela/leancheck-instances
+[hackage-version]: https://img.shields.io/hackage/v/leancheck-instances.svg
+[leancheck-instances-on-hackage]:          https://hackage.haskell.org/package/leancheck-instances
+[stackage-lts-badge]:                      http://stackage.org/package/leancheck-instances/badge/lts
+[stackage-nightly-badge]:                  http://stackage.org/package/leancheck-instances/badge/nightly
+[leancheck-instances-on-stackage]:         http://stackage.org/package/leancheck-instances
+[leancheck-instances-on-stackage-lts]:     http://stackage.org/lts/package/leancheck-instances
+[leancheck-instances-on-stackage-nightly]: http://stackage.org/nightly/package/leancheck-instances
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/TODO.md b/TODO.md
new file mode 100644
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,13 @@
+TO DO list for leancheck-instances
+==================================
+
+List of things to do for leancheck-instances.
+
+
+1. add support for most types supported by quickcheck-instances (& release);
+
+2. add support for all types supported by quickcheck-instances (& release);
+
+* add `WithInstances` module;
+
+* support more types?
diff --git a/bench/tiers.hs b/bench/tiers.hs
new file mode 100644
--- /dev/null
+++ b/bench/tiers.hs
@@ -0,0 +1,98 @@
+-- tiers.hs -- prints tiers of values up to a certain point
+--
+-- Copyright (c) 2015-2018 Rudy Matela.
+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
+import Test.LeanCheck
+import Test.LeanCheck.Instances
+import Test.LeanCheck.Function
+import Test.LeanCheck.Function.Eq
+import Test.LeanCheck.Tiers (showTiers, finite)
+import System.Environment
+import qualified Data.ByteString as BS
+import Data.List (intercalate, nub)
+import Data.Ratio ((%))
+import Data.Text (Text)
+import Numeric.Natural
+
+dropEmptyTiersTail :: [[a]] -> [[a]]
+dropEmptyTiersTail ([]:[]:[]: []:[]:[]: _) = []
+dropEmptyTiersTail (xs:xss) = xs:dropEmptyTiersTail xss
+dropEmptyTiersTail []     = []
+
+lengthT :: [[a]] -> Maybe Int
+lengthT xss | finite xss' = Just . length $ concat xss'
+            | otherwise   = Nothing
+  where xss' = dropEmptyTiersTail xss
+
+allUnique :: Eq a => [a] -> Bool
+allUnique [] = True
+allUnique (x:xs) = x `notElem` xs
+                && allUnique (filter (/= x) xs)
+
+countRepetitions :: Eq a => [a] -> Int
+countRepetitions xs = length xs - length (nub xs)
+
+ratioRepetitions :: Eq a => [a] -> Rational
+ratioRepetitions [] = 0
+ratioRepetitions xs = fromIntegral (countRepetitions xs) % fromIntegral (length xs)
+
+showLengthT :: [[a]] -> String
+showLengthT xss = case lengthT xss of
+                    Nothing -> "Infinity"
+                    Just x  -> show x
+
+showDotsLongerThan :: Show a => Int -> [a] -> String
+showDotsLongerThan n xs = "["
+                       ++ intercalate "," (dotsLongerThan n $ map show xs)
+                       ++ "]"
+  where
+  dotsLongerThan n xs = take n xs ++ ["..." | not . null $ drop n xs]
+
+printTiers :: Show a => Int -> [[a]] -> IO ()
+printTiers n = putStrLn . init . unlines . map ("  " ++) . lines . showTiers n
+
+put :: (Show a, Eq a, Listable a) => String -> Int -> a -> IO ()
+put t n a = do
+  putStrLn $ "map length (tiers :: [[ " ++ t ++ " ]])  =  "
+          ++ showDotsLongerThan n (map length $ tiers `asTypeOf` [[a]])
+  putStrLn $ ""
+  putStrLn $ "length (list :: [ " ++ t ++ " ])  =  "
+          ++ showLengthT (tiers `asTypeOf` [[a]])
+  putStrLn $ ""
+  putStrLn $ "allUnique (list :: [ " ++ t ++ " ])  =  "
+          ++ show (allUnique . concat . take n $ tiers `asTypeOf` [[a]])
+  putStrLn $ ""
+  putStrLn $ "ratioRepetitions (list :: [ " ++ t ++ " ])  =  "
+          ++ show (ratioRepetitions . concat . take n $ tiers `asTypeOf` [[a]])
+  putStrLn $ ""
+  putStrLn $ "tiers :: [" ++ t ++ "]  ="
+  printTiers n $ tiers `asTypeOf` [[a]]
+
+u :: a
+u = undefined
+
+main :: IO ()
+main = do
+  as <- getArgs
+  let (t,n) = case as of
+                []    -> ("Int", 12)
+                [t]   -> (t,     12)
+                [t,n] -> (t, read n)
+  case t of
+    -- standard types
+    "()"               -> put t n (u :: ()                   )
+    "Int"              -> put t n (u :: Int                  )
+    "Integer"          -> put t n (u :: Integer              )
+    "Bool"             -> put t n (u :: Bool                 )
+    "Char"             -> put t n (u :: Char                 )
+    "Float"            -> put t n (u :: Float                )
+    "Double"           -> put t n (u :: Double               )
+    "Rational"         -> put t n (u :: Rational             )
+    "[()]"             -> put t n (u :: [()]                 )
+    "[Int]"            -> put t n (u :: [Int]                )
+    -- other
+    "Text"             -> put t n (u :: Text                 )
+    "Natural"          -> put t n (u :: Natural              )
+    "ByteString"       -> put t n (u :: BS.ByteString        )
+    -- unhandled
+    _                  -> putStrLn $ "unknown/unhandled type `" ++ t ++ "'"
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,10 @@
+Changelog for leancheck-instances
+=================================
+
+v0.0.1
+------
+
+* ByteString instances;
+* Natural instance;
+* Text instance;
+* initial release on Hackage.
diff --git a/eg/test-text.hs b/eg/test-text.hs
new file mode 100644
--- /dev/null
+++ b/eg/test-text.hs
@@ -0,0 +1,31 @@
+-- test-list.hs -- example program, testing Data.List using LeanCheck
+--
+-- Copyright (c) 2017-2018 Rudy Matela.
+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
+import Test.LeanCheck
+import Test.LeanCheck.Instances
+import Data.Char
+import Data.Text as T
+import Prelude as P hiding (lines, unlines, words, unwords)
+
+main :: IO ()
+main = do
+  -- wrong: append is clearly not commutative
+  check $ \t1 t2 -> t1 `append` t2 == t2 `append` t1
+
+  -- wrong: lines and unlines do not form an identity
+  check $ \ts -> lines (unlines ts) == ts
+  check $ \t ->   unlines (lines t) == t
+
+  -- correct: lines and unlines form an identity under certain conditions
+  check $ \ts -> P.all (T.all isAlphaNum) ts
+             ==> lines (unlines ts) == ts
+  check $ \ts -> unlines (lines (unlines ts)) == unlines ts
+  check $ \ts ->   lines (unlines (lines ts)) == lines ts
+
+  -- wrong: words and unwords do not form an identity
+  check $ \ts -> words (unwords ts) == ts
+  check $ \t ->   unwords (words t) == t
+
+  -- correct: words and unwords form an identity under certain conditions
+  check $ \ts ->   words (unwords (words ts)) == words ts
diff --git a/leancheck-instances.cabal b/leancheck-instances.cabal
new file mode 100644
--- /dev/null
+++ b/leancheck-instances.cabal
@@ -0,0 +1,81 @@
+-- Cabal file for leancheck-instances
+name:                leancheck-instances
+version:             0.0.1
+synopsis:            Common LeanCheck instances
+description:
+  Listable instances for types provided by the Haskell Platform.
+  .
+  The current objective is to include all types supported by quickcheck-instances:
+  <https://hackage.haskell.org/package/quickcheck-instances>
+
+homepage:            https://github.com/rudymatela/leancheck-instances#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Rudy Matela <rudy@matela.com.br>
+maintainer:          Rudy Matela <rudy@matela.com.br>
+category:            Testing
+build-type:          Simple
+cabal-version:       1.18
+
+extra-doc-files: README.md
+               , TODO.md
+               , changelog.md
+extra-source-files: .gitignore
+                  , .travis.yml
+                  , Makefile
+                  , bench/tiers.hs
+                  , eg/test-text.hs
+                  , mk/All.hs
+                  , mk/Toplibs.hs
+                  , mk/depend.mk
+                  , mk/ghcdeps
+                  , mk/haddock-i
+                  , mk/haskell.mk
+                  , stack.yaml
+                  , test/diff/*.out
+                  , test/diff/eg/*.out
+                  , test/sdist
+tested-with: GHC==8.6, GHC==8.4, GHC==8.2, GHC==8.0
+           , GHC==7.10, GHC==7.8
+
+
+source-repository head
+  type:            git
+  location:        https://github.com/rudymatela/leancheck-instances
+
+source-repository this
+  type:            git
+  location:        https://github.com/rudymatela/leancheck-instances
+  tag:             v0.0.1
+
+library
+  exposed-modules: Test.LeanCheck.Instances
+                 , Test.LeanCheck.Instances.Text
+                 , Test.LeanCheck.Instances.Natural
+                 , Test.LeanCheck.Instances.ByteString
+  hs-source-dirs: src
+  build-depends: base >= 4 && < 5
+               , leancheck
+               , bytestring
+               , nats
+               , text
+  default-language: Haskell2010
+
+test-suite main
+  type:                exitcode-stdio-1.0
+  main-is:             main.hs
+  hs-source-dirs:      test
+  build-depends:       base >= 4 && < 5
+                     , leancheck
+                     , leancheck-instances
+                     , bytestring
+                     , nats
+                     , text
+  default-language:    Haskell2010
+
+test-suite text
+  type:                exitcode-stdio-1.0
+  main-is:             text.hs
+  hs-source-dirs:      test
+  build-depends:       base >= 4 && < 5, leancheck, leancheck-instances, text
+  default-language:    Haskell2010
diff --git a/mk/All.hs b/mk/All.hs
new file mode 100644
--- /dev/null
+++ b/mk/All.hs
@@ -0,0 +1,7 @@
+module All
+  ( module Test.LeanCheck
+  )
+where
+
+import Test.LeanCheck
+import Test.LeanCheck.Instances
diff --git a/mk/Toplibs.hs b/mk/Toplibs.hs
new file mode 100644
--- /dev/null
+++ b/mk/Toplibs.hs
@@ -0,0 +1,4 @@
+-- Using ghc --make in this module triggers compilation of every library.
+module Toplibs () where
+
+import Test.LeanCheck.Instances ()
diff --git a/mk/depend.mk b/mk/depend.mk
new file mode 100644
--- /dev/null
+++ b/mk/depend.mk
@@ -0,0 +1,55 @@
+bench/tiers: \
+  bench/tiers.hs \
+  mk/toplibs
+bench/tiers.o: \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs \
+  bench/tiers.hs
+eg/test-text: \
+  eg/test-text.hs \
+  mk/toplibs
+eg/test-text.o: \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs \
+  eg/test-text.hs
+mk/All.o: \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs \
+  mk/All.hs
+mk/Toplibs.o: \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs \
+  mk/Toplibs.hs
+Setup.o: \
+  Setup.hs
+Setup: \
+  Setup.hs \
+  mk/toplibs
+src/Test/LeanCheck/Instances/Natural.o: \
+  src/Test/LeanCheck/Instances/Natural.hs
+src/Test/LeanCheck/Instances.o: \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs
+src/Test/LeanCheck/Instances/Text.o: \
+  src/Test/LeanCheck/Instances/Text.hs
+test/main.o: \
+  test/main.hs \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs
+test/main: \
+  test/main.hs \
+  mk/toplibs
+test/text.o: \
+  test/text.hs \
+  src/Test/LeanCheck/Instances/Text.hs \
+  src/Test/LeanCheck/Instances.hs \
+  src/Test/LeanCheck/Instances/Natural.hs
+test/text: \
+  test/text.hs \
+  mk/toplibs
diff --git a/mk/ghcdeps b/mk/ghcdeps
new file mode 100644
--- /dev/null
+++ b/mk/ghcdeps
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+# ghcdeps: generate Haskell make dependencies for compiling with GHC.
+#
+# Copyright (c) 2015-2018 Rudy Matela.
+# Distributed under the 3-Clause BSD licence.
+#
+# From a list of files provided on standard input,
+# generate flat make dependencies.
+#
+# Transitive relations are repeated.
+#
+# Usage:
+#   $ ghcdeps -isomedir:someother <<LIST
+#   program.hs
+#   Library.hs
+#   Path/To/Library.hs
+#   LIST
+#   program: ...
+#   Library.o: ...
+#   Path/To/Library.o: ...
+#
+# Or:
+#   $ find -name \*.hs -o -name \*.lhs | ghcdeps [GHCFLAGS]
+#   ...
+#
+# Note that when using find, you have to remember to exclude unecessary files,
+# e.g.:  dist, Setup.hs
+#
+# Yes, this is hacky.  But hey, it works.
+while read fn
+do
+	ghc "$@" -dep-suffix=. -dep-makefile=tmp.mk -M "$fn" ||
+	exit 1
+	deps="`cat tmp.mk |
+	       grep "hs$" |
+	       sort |
+	       sed -e "s/.*: //" |
+	       tac |
+	       tr '\n' ' ' |
+	       sed -e "s/ $//"`"
+	obj=`echo $fn | sed -e 's,^\./,,;s/\.hs$/.o/'`
+	bin=`echo $fn | sed -e 's,^\./,,;s/\.hs$//'`
+	echo "$obj: $deps"
+	grep -q "main" "$fn" && echo "$bin: `echo $deps | sed -e 's|[^ ]*src[^ ]*||g'` mk/toplibs"
+	rm -f tmp.mk
+done |
+sort |
+sed -e 's,  *, \\\n  ,g'
diff --git a/mk/haddock-i b/mk/haddock-i
new file mode 100644
--- /dev/null
+++ b/mk/haddock-i
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# haddock-i: list haddock's -i parameters.
+#
+# Copyright (c) 2015-2018 Rudy Matela.
+# Distributed under the 3-Clause BSD licence.
+#
+# $ haddock-i <package1> <package2> ... <packageN>
+#
+# will print -i parameters necessary for haddock to link to Haddock
+# documentation installed on your system, so you can:
+#
+# $ haddock-i base template-haskell | xargs haddock <files>
+errxit() {
+	echo "$@" > /dev/stderr
+	exit 1
+}
+
+for pkg in "$@"; do
+	ghc-pkg field $pkg haddock-html,haddock-interfaces ||
+	errxit "error: haddock-i: cannot find package $pkg (ghc-pkg)"
+done |
+sed "s/.*: //" |
+sed "N;s/\n/,/;s/^/-i/"
diff --git a/mk/haskell.mk b/mk/haskell.mk
new file mode 100644
--- /dev/null
+++ b/mk/haskell.mk
@@ -0,0 +1,116 @@
+# Implicit rules for compiling Haskell code.
+#
+# Copyright (c) 2015-2018 Rudy Matela.
+# Distributed under the 3-Clause BSD licence.
+#
+# You can optionally configure the "Configuration variables" below in your main
+# makefile, e.g.:
+#
+#   GHCIMPORTDIRS = path/to/dir:path/to/another/dir
+#   GHCFLAGS = -O2 -dynamic
+#   GHC = ghc-7.6
+#   include haskell.mk
+
+
+
+# Configuration variables
+
+# GHC Parameters
+GHCIMPORTDIRS ?=
+GHCFLAGS ?=
+GHC ?= ghc
+GHCCMD = $(GHC) -i$(GHCIMPORTDIRS) $(GHCFLAGS)
+
+# Hugs Parameters
+HUGSIMPORTDIRS ?= "/usr/lib/hugs/packages/*"
+HUGSFLAGS ?=
+CPPHS_HUGS ?= cpphs-hugs --noline -D__HUGS__
+HUGS ?= hugs
+RUNHUGS ?= runhugs
+HUGSCMD    = $(HUGS)    -F"$(CPPHS_HUGS)" -P$(HUGSIMPORTDIRS) $(HUGSFLAGS)
+RUNHUGSCMD = $(RUNHUGS) -F"$(CPPHS_HUGS)" -P$(HUGSIMPORTDIRS) $(HUGSFLAGS)
+
+
+# Makefile where to keep the dependencies
+DEPMK ?= mk/depend.mk
+
+# LIB_HSS: all library Haskell files
+# ALL_HSS: all Haskell files
+# You can override ALL/LIB_HSS in your main Makefile
+LIST_LIB_HSS ?= find src -name "*.hs"
+LIST_ALL_HSS ?= find \( -path "./dist" -o -path "./.stack-work" \) -prune \
+                     -o -name "*.*hs" -print
+LIB_HSS ?= $(shell $(LIST_LIB_HSS))
+ALL_HSS ?= $(shell $(LIST_ALL_HSS))
+
+PKGNAME = $(shell cat *.cabal | grep "^name:"    | sed -e "s/name: *//")
+HADDOCK_VERSION = $(shell haddock --version | grep version | sed -e 's/.*version //;s/,.*//')
+HADDOCK_MAJOR = $(shell echo $(HADDOCK_VERSION) | sed -e 's/\..*//')
+HADDOCK_MINOR = $(shell echo $(HADDOCK_VERSION) | sed -e 's/[0-9]*\.\([0-9]*\).[0-9]*/\1/')
+HADDOCK_PKG_NAME = $(shell [ $(HADDOCK_MAJOR) -gt 2 ] \
+                        || [ $(HADDOCK_MAJOR) -eq 2 -a $(HADDOCK_MINOR) -ge 20 ] \
+                        && echo "--package-name=$(PKGNAME)")
+
+
+# Implicit rules
+%.hi %.o: %.hs
+	$(GHCCMD) $< && touch $@
+
+%: %.hs
+	$(GHCCMD) $< && touch $@
+
+.PHONY: %.ghci
+%.ghci: %.hs
+	$(GHCCMD) -O0 --interactive $<
+
+.PHONY: %.hugs
+%.hugs: %.hs
+	$(HUGSCMD) $<
+
+.PHONY: %.runhugs
+%.runhugs: %.hs
+	$(RUNHUGSCMD) $<
+
+
+# Cleaning rule (add as a clean dependency)
+.PHONY: clean-hi-o
+clean-hi-o:
+	find $(ALL_HSS) | sed -e 's/hs$$/o/'      | xargs rm -f
+	find $(ALL_HSS) | sed -e 's/hs$$/hi/'     | xargs rm -f
+	find $(ALL_HSS) | sed -e 's/hs$$/dyn_o/'  | xargs rm -f
+	find $(ALL_HSS) | sed -e 's/hs$$/dyn_hi/' | xargs rm -f
+
+
+# Update dependency file
+.PHONY: depend
+depend:
+	find $(ALL_HSS) | ./mk/ghcdeps -i$(GHCIMPORTDIRS) $(GHCFLAGS) > $(DEPMK)
+
+# haddock rules
+haddock: doc/index.html
+
+clean-haddock:
+	rm -f doc/*.{html,css,js,png,gif,json} README.html
+
+upload-haddock:
+	@echo "use \`cabal upload -d' instead"
+	@echo "(but 1st: cabal install --only-dependencies --enable-documentation)"
+	@echo "(to just compile docs: cabal haddock --for-hackage)"
+	@echo "(on Arch Linux, use: cabal haddock --for-hackage --haddock-options=--optghc=-dynamic)"
+
+doc/index.html: $(LIB_HSS)
+	./mk/haddock-i base template-haskell | xargs \
+	haddock --html -odoc $(LIB_HSS) $(HADDOCKFLAGS) --title=$(PKGNAME) $(HADDOCK_PKG_NAME)
+
+# lists all Haskell source files
+list-all-hss:
+	@find $(ALL_HSS)
+
+# lists library Haskell source files
+list-lib-hss:
+	@find $(LIB_HSS)
+
+show-pkgname:
+	@echo $(PKGNAME)
+
+include $(DEPMK)
diff --git a/src/Test/LeanCheck/Instances.hs b/src/Test/LeanCheck/Instances.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/LeanCheck/Instances.hs
@@ -0,0 +1,5 @@
+module Test.LeanCheck.Instances () where
+
+import Test.LeanCheck.Instances.Text
+import Test.LeanCheck.Instances.Natural
+import Test.LeanCheck.Instances.ByteString
diff --git a/src/Test/LeanCheck/Instances/ByteString.hs b/src/Test/LeanCheck/Instances/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/LeanCheck/Instances/ByteString.hs
@@ -0,0 +1,18 @@
+module Test.LeanCheck.Instances.ByteString () where
+
+import Test.LeanCheck
+import Data.ByteString.Lazy as Lazy
+import Data.ByteString as Strict
+import Data.Word
+
+tiersBytes :: [[ Word8 ]]
+tiersBytes = toTiers $ [0..127] +| [255,254..128]
+
+tiersListBytes :: [[ [Word8] ]]
+tiersListBytes = listsOf tiersBytes
+
+instance Listable Lazy.ByteString where
+  tiers = mapT Lazy.pack tiersListBytes
+
+instance Listable Strict.ByteString where
+  tiers = mapT Strict.pack tiersListBytes
diff --git a/src/Test/LeanCheck/Instances/Natural.hs b/src/Test/LeanCheck/Instances/Natural.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/LeanCheck/Instances/Natural.hs
@@ -0,0 +1,7 @@
+module Test.LeanCheck.Instances.Natural () where
+
+import Numeric.Natural
+import Test.LeanCheck
+
+instance Listable Natural where
+  list = [0..]
diff --git a/src/Test/LeanCheck/Instances/Text.hs b/src/Test/LeanCheck/Instances/Text.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/LeanCheck/Instances/Text.hs
@@ -0,0 +1,7 @@
+module Test.LeanCheck.Instances.Text () where
+
+import Data.Text
+import Test.LeanCheck
+
+instance Listable Text where
+  tiers = cons1 pack
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,15 @@
+# stack.yaml docs:
+# https://docs.haskellstack.org/en/stable/yaml_configuration/
+
+# resolver: nightly-2015-09-21
+# resolver: ghc-7.10.2
+resolver: lts-12.14
+
+packages:
+- .
+
+extra-deps: []
+
+flags: {}
+
+extra-package-dbs: []
diff --git a/test/diff/eg/test-text.out b/test/diff/eg/test-text.out
new file mode 100644
--- /dev/null
+++ b/test/diff/eg/test-text.out
@@ -0,0 +1,14 @@
+*** Failed! Falsifiable (after 14 tests):
+"a" " "
+*** Failed! Falsifiable (after 127 tests):
+["\n"]
+*** Failed! Falsifiable (after 2 tests):
+"a"
++++ OK, passed 200 tests.
++++ OK, passed 200 tests.
++++ OK, passed 200 tests.
+*** Failed! Falsifiable (after 2 tests):
+[""]
+*** Failed! Falsifiable (after 4 tests):
+" "
++++ OK, passed 200 tests.
diff --git a/test/diff/tiers-ByteString.out b/test/diff/tiers-ByteString.out
new file mode 100644
--- /dev/null
+++ b/test/diff/tiers-ByteString.out
@@ -0,0 +1,47 @@
+map length (tiers :: [[ ByteString ]])  =  [1,1,2,4,8,16,...]
+
+length (list :: [ ByteString ])  =  Infinity
+
+allUnique (list :: [ ByteString ])  =  True
+
+ratioRepetitions (list :: [ ByteString ])  =  0 % 1
+
+tiers :: [ByteString]  =
+  [ [""]
+  , ["\NUL"]
+  , [ "\NUL\NUL"
+    , "\255"
+    ]
+  , [ "\NUL\NUL\NUL"
+    , "\NUL\255"
+    , "\255\NUL"
+    , "\SOH"
+    ]
+  , [ "\NUL\NUL\NUL\NUL"
+    , "\NUL\NUL\255"
+    , "\NUL\255\NUL"
+    , "\NUL\SOH"
+    , "\255\NUL\NUL"
+    , "\255\255"
+    , "\SOH\NUL"
+    , "\254"
+    ]
+  , [ "\NUL\NUL\NUL\NUL\NUL"
+    , "\NUL\NUL\NUL\255"
+    , "\NUL\NUL\255\NUL"
+    , "\NUL\NUL\SOH"
+    , "\NUL\255\NUL\NUL"
+    , "\NUL\255\255"
+    , "\NUL\SOH\NUL"
+    , "\NUL\254"
+    , "\255\NUL\NUL\NUL"
+    , "\255\NUL\255"
+    , "\255\255\NUL"
+    , "\255\SOH"
+    , "\SOH\NUL\NUL"
+    , "\SOH\255"
+    , "\254\NUL"
+    , "\STX"
+    ]
+  , ...
+  ]
diff --git a/test/diff/tiers-Natural.out b/test/diff/tiers-Natural.out
new file mode 100644
--- /dev/null
+++ b/test/diff/tiers-Natural.out
@@ -0,0 +1,23 @@
+map length (tiers :: [[ Natural ]])  =  [1,1,1,1,1,1,1,1,1,1,1,1,...]
+
+length (list :: [ Natural ])  =  Infinity
+
+allUnique (list :: [ Natural ])  =  True
+
+ratioRepetitions (list :: [ Natural ])  =  0 % 1
+
+tiers :: [Natural]  =
+  [ [0]
+  , [1]
+  , [2]
+  , [3]
+  , [4]
+  , [5]
+  , [6]
+  , [7]
+  , [8]
+  , [9]
+  , [10]
+  , [11]
+  , ...
+  ]
diff --git a/test/diff/tiers-Text.out b/test/diff/tiers-Text.out
new file mode 100644
--- /dev/null
+++ b/test/diff/tiers-Text.out
@@ -0,0 +1,1045 @@
+map length (tiers :: [[ Text ]])  =  [0,1,1,2,4,8,16,32,64,128,256,512,...]
+
+length (list :: [ Text ])  =  Infinity
+
+allUnique (list :: [ Text ])  =  True
+
+ratioRepetitions (list :: [ Text ])  =  0 % 1
+
+tiers :: [Text]  =
+  [ []
+  , [""]
+  , ["a"]
+  , [ "aa"
+    , " "
+    ]
+  , [ "aaa"
+    , "a "
+    , " a"
+    , "b"
+    ]
+  , [ "aaaa"
+    , "aa "
+    , "a a"
+    , "ab"
+    , " aa"
+    , "  "
+    , "ba"
+    , "A"
+    ]
+  , [ "aaaaa"
+    , "aaa "
+    , "aa a"
+    , "aab"
+    , "a aa"
+    , "a  "
+    , "aba"
+    , "aA"
+    , " aaa"
+    , " a "
+    , "  a"
+    , " b"
+    , "baa"
+    , "b "
+    , "Aa"
+    , "c"
+    ]
+  , [ "aaaaaa"
+    , "aaaa "
+    , "aaa a"
+    , "aaab"
+    , "aa aa"
+    , "aa  "
+    , "aaba"
+    , "aaA"
+    , "a aaa"
+    , "a a "
+    , "a  a"
+    , "a b"
+    , "abaa"
+    , "ab "
+    , "aAa"
+    , "ac"
+    , " aaaa"
+    , " aa "
+    , " a a"
+    , " ab"
+    , "  aa"
+    , "   "
+    , " ba"
+    , " A"
+    , "baaa"
+    , "ba "
+    , "b a"
+    , "bb"
+    , "Aaa"
+    , "A "
+    , "ca"
+    , "\n"
+    ]
+  , [ "aaaaaaa"
+    , "aaaaa "
+    , "aaaa a"
+    , "aaaab"
+    , "aaa aa"
+    , "aaa  "
+    , "aaaba"
+    , "aaaA"
+    , "aa aaa"
+    , "aa a "
+    , "aa  a"
+    , "aa b"
+    , "aabaa"
+    , "aab "
+    , "aaAa"
+    , "aac"
+    , "a aaaa"
+    , "a aa "
+    , "a a a"
+    , "a ab"
+    , "a  aa"
+    , "a   "
+    , "a ba"
+    , "a A"
+    , "abaaa"
+    , "aba "
+    , "ab a"
+    , "abb"
+    , "aAaa"
+    , "aA "
+    , "aca"
+    , "a\n"
+    , " aaaaa"
+    , " aaa "
+    , " aa a"
+    , " aab"
+    , " a aa"
+    , " a  "
+    , " aba"
+    , " aA"
+    , "  aaa"
+    , "  a "
+    , "   a"
+    , "  b"
+    , " baa"
+    , " b "
+    , " Aa"
+    , " c"
+    , "baaaa"
+    , "baa "
+    , "ba a"
+    , "bab"
+    , "b aa"
+    , "b  "
+    , "bba"
+    , "bA"
+    , "Aaaa"
+    , "Aa "
+    , "A a"
+    , "Ab"
+    , "caa"
+    , "c "
+    , "\na"
+    , "d"
+    ]
+  , [ "aaaaaaaa"
+    , "aaaaaa "
+    , "aaaaa a"
+    , "aaaaab"
+    , "aaaa aa"
+    , "aaaa  "
+    , "aaaaba"
+    , "aaaaA"
+    , "aaa aaa"
+    , "aaa a "
+    , "aaa  a"
+    , "aaa b"
+    , "aaabaa"
+    , "aaab "
+    , "aaaAa"
+    , "aaac"
+    , "aa aaaa"
+    , "aa aa "
+    , "aa a a"
+    , "aa ab"
+    , "aa  aa"
+    , "aa   "
+    , "aa ba"
+    , "aa A"
+    , "aabaaa"
+    , "aaba "
+    , "aab a"
+    , "aabb"
+    , "aaAaa"
+    , "aaA "
+    , "aaca"
+    , "aa\n"
+    , "a aaaaa"
+    , "a aaa "
+    , "a aa a"
+    , "a aab"
+    , "a a aa"
+    , "a a  "
+    , "a aba"
+    , "a aA"
+    , "a  aaa"
+    , "a  a "
+    , "a   a"
+    , "a  b"
+    , "a baa"
+    , "a b "
+    , "a Aa"
+    , "a c"
+    , "abaaaa"
+    , "abaa "
+    , "aba a"
+    , "abab"
+    , "ab aa"
+    , "ab  "
+    , "abba"
+    , "abA"
+    , "aAaaa"
+    , "aAa "
+    , "aA a"
+    , "aAb"
+    , "acaa"
+    , "ac "
+    , "a\na"
+    , "ad"
+    , " aaaaaa"
+    , " aaaa "
+    , " aaa a"
+    , " aaab"
+    , " aa aa"
+    , " aa  "
+    , " aaba"
+    , " aaA"
+    , " a aaa"
+    , " a a "
+    , " a  a"
+    , " a b"
+    , " abaa"
+    , " ab "
+    , " aAa"
+    , " ac"
+    , "  aaaa"
+    , "  aa "
+    , "  a a"
+    , "  ab"
+    , "   aa"
+    , "    "
+    , "  ba"
+    , "  A"
+    , " baaa"
+    , " ba "
+    , " b a"
+    , " bb"
+    , " Aaa"
+    , " A "
+    , " ca"
+    , " \n"
+    , "baaaaa"
+    , "baaa "
+    , "baa a"
+    , "baab"
+    , "ba aa"
+    , "ba  "
+    , "baba"
+    , "baA"
+    , "b aaa"
+    , "b a "
+    , "b  a"
+    , "b b"
+    , "bbaa"
+    , "bb "
+    , "bAa"
+    , "bc"
+    , "Aaaaa"
+    , "Aaa "
+    , "Aa a"
+    , "Aab"
+    , "A aa"
+    , "A  "
+    , "Aba"
+    , "AA"
+    , "caaa"
+    , "ca "
+    , "c a"
+    , "cb"
+    , "\naa"
+    , "\n "
+    , "da"
+    , "0"
+    ]
+  , [ "aaaaaaaaa"
+    , "aaaaaaa "
+    , "aaaaaa a"
+    , "aaaaaab"
+    , "aaaaa aa"
+    , "aaaaa  "
+    , "aaaaaba"
+    , "aaaaaA"
+    , "aaaa aaa"
+    , "aaaa a "
+    , "aaaa  a"
+    , "aaaa b"
+    , "aaaabaa"
+    , "aaaab "
+    , "aaaaAa"
+    , "aaaac"
+    , "aaa aaaa"
+    , "aaa aa "
+    , "aaa a a"
+    , "aaa ab"
+    , "aaa  aa"
+    , "aaa   "
+    , "aaa ba"
+    , "aaa A"
+    , "aaabaaa"
+    , "aaaba "
+    , "aaab a"
+    , "aaabb"
+    , "aaaAaa"
+    , "aaaA "
+    , "aaaca"
+    , "aaa\n"
+    , "aa aaaaa"
+    , "aa aaa "
+    , "aa aa a"
+    , "aa aab"
+    , "aa a aa"
+    , "aa a  "
+    , "aa aba"
+    , "aa aA"
+    , "aa  aaa"
+    , "aa  a "
+    , "aa   a"
+    , "aa  b"
+    , "aa baa"
+    , "aa b "
+    , "aa Aa"
+    , "aa c"
+    , "aabaaaa"
+    , "aabaa "
+    , "aaba a"
+    , "aabab"
+    , "aab aa"
+    , "aab  "
+    , "aabba"
+    , "aabA"
+    , "aaAaaa"
+    , "aaAa "
+    , "aaA a"
+    , "aaAb"
+    , "aacaa"
+    , "aac "
+    , "aa\na"
+    , "aad"
+    , "a aaaaaa"
+    , "a aaaa "
+    , "a aaa a"
+    , "a aaab"
+    , "a aa aa"
+    , "a aa  "
+    , "a aaba"
+    , "a aaA"
+    , "a a aaa"
+    , "a a a "
+    , "a a  a"
+    , "a a b"
+    , "a abaa"
+    , "a ab "
+    , "a aAa"
+    , "a ac"
+    , "a  aaaa"
+    , "a  aa "
+    , "a  a a"
+    , "a  ab"
+    , "a   aa"
+    , "a    "
+    , "a  ba"
+    , "a  A"
+    , "a baaa"
+    , "a ba "
+    , "a b a"
+    , "a bb"
+    , "a Aaa"
+    , "a A "
+    , "a ca"
+    , "a \n"
+    , "abaaaaa"
+    , "abaaa "
+    , "abaa a"
+    , "abaab"
+    , "aba aa"
+    , "aba  "
+    , "ababa"
+    , "abaA"
+    , "ab aaa"
+    , "ab a "
+    , "ab  a"
+    , "ab b"
+    , "abbaa"
+    , "abb "
+    , "abAa"
+    , "abc"
+    , "aAaaaa"
+    , "aAaa "
+    , "aAa a"
+    , "aAab"
+    , "aA aa"
+    , "aA  "
+    , "aAba"
+    , "aAA"
+    , "acaaa"
+    , "aca "
+    , "ac a"
+    , "acb"
+    , "a\naa"
+    , "a\n "
+    , "ada"
+    , "a0"
+    , " aaaaaaa"
+    , " aaaaa "
+    , " aaaa a"
+    , " aaaab"
+    , " aaa aa"
+    , " aaa  "
+    , " aaaba"
+    , " aaaA"
+    , " aa aaa"
+    , " aa a "
+    , " aa  a"
+    , " aa b"
+    , " aabaa"
+    , " aab "
+    , " aaAa"
+    , " aac"
+    , " a aaaa"
+    , " a aa "
+    , " a a a"
+    , " a ab"
+    , " a  aa"
+    , " a   "
+    , " a ba"
+    , " a A"
+    , " abaaa"
+    , " aba "
+    , " ab a"
+    , " abb"
+    , " aAaa"
+    , " aA "
+    , " aca"
+    , " a\n"
+    , "  aaaaa"
+    , "  aaa "
+    , "  aa a"
+    , "  aab"
+    , "  a aa"
+    , "  a  "
+    , "  aba"
+    , "  aA"
+    , "   aaa"
+    , "   a "
+    , "    a"
+    , "   b"
+    , "  baa"
+    , "  b "
+    , "  Aa"
+    , "  c"
+    , " baaaa"
+    , " baa "
+    , " ba a"
+    , " bab"
+    , " b aa"
+    , " b  "
+    , " bba"
+    , " bA"
+    , " Aaaa"
+    , " Aa "
+    , " A a"
+    , " Ab"
+    , " caa"
+    , " c "
+    , " \na"
+    , " d"
+    , "baaaaaa"
+    , "baaaa "
+    , "baaa a"
+    , "baaab"
+    , "baa aa"
+    , "baa  "
+    , "baaba"
+    , "baaA"
+    , "ba aaa"
+    , "ba a "
+    , "ba  a"
+    , "ba b"
+    , "babaa"
+    , "bab "
+    , "baAa"
+    , "bac"
+    , "b aaaa"
+    , "b aa "
+    , "b a a"
+    , "b ab"
+    , "b  aa"
+    , "b   "
+    , "b ba"
+    , "b A"
+    , "bbaaa"
+    , "bba "
+    , "bb a"
+    , "bbb"
+    , "bAaa"
+    , "bA "
+    , "bca"
+    , "b\n"
+    , "Aaaaaa"
+    , "Aaaa "
+    , "Aaa a"
+    , "Aaab"
+    , "Aa aa"
+    , "Aa  "
+    , "Aaba"
+    , "AaA"
+    , "A aaa"
+    , "A a "
+    , "A  a"
+    , "A b"
+    , "Abaa"
+    , "Ab "
+    , "AAa"
+    , "Ac"
+    , "caaaa"
+    , "caa "
+    , "ca a"
+    , "cab"
+    , "c aa"
+    , "c  "
+    , "cba"
+    , "cA"
+    , "\naaa"
+    , "\na "
+    , "\n a"
+    , "\nb"
+    , "daa"
+    , "d "
+    , "0a"
+    , "e"
+    ]
+  , [ "aaaaaaaaaa"
+    , "aaaaaaaa "
+    , "aaaaaaa a"
+    , "aaaaaaab"
+    , "aaaaaa aa"
+    , "aaaaaa  "
+    , "aaaaaaba"
+    , "aaaaaaA"
+    , "aaaaa aaa"
+    , "aaaaa a "
+    , "aaaaa  a"
+    , "aaaaa b"
+    , "aaaaabaa"
+    , "aaaaab "
+    , "aaaaaAa"
+    , "aaaaac"
+    , "aaaa aaaa"
+    , "aaaa aa "
+    , "aaaa a a"
+    , "aaaa ab"
+    , "aaaa  aa"
+    , "aaaa   "
+    , "aaaa ba"
+    , "aaaa A"
+    , "aaaabaaa"
+    , "aaaaba "
+    , "aaaab a"
+    , "aaaabb"
+    , "aaaaAaa"
+    , "aaaaA "
+    , "aaaaca"
+    , "aaaa\n"
+    , "aaa aaaaa"
+    , "aaa aaa "
+    , "aaa aa a"
+    , "aaa aab"
+    , "aaa a aa"
+    , "aaa a  "
+    , "aaa aba"
+    , "aaa aA"
+    , "aaa  aaa"
+    , "aaa  a "
+    , "aaa   a"
+    , "aaa  b"
+    , "aaa baa"
+    , "aaa b "
+    , "aaa Aa"
+    , "aaa c"
+    , "aaabaaaa"
+    , "aaabaa "
+    , "aaaba a"
+    , "aaabab"
+    , "aaab aa"
+    , "aaab  "
+    , "aaabba"
+    , "aaabA"
+    , "aaaAaaa"
+    , "aaaAa "
+    , "aaaA a"
+    , "aaaAb"
+    , "aaacaa"
+    , "aaac "
+    , "aaa\na"
+    , "aaad"
+    , "aa aaaaaa"
+    , "aa aaaa "
+    , "aa aaa a"
+    , "aa aaab"
+    , "aa aa aa"
+    , "aa aa  "
+    , "aa aaba"
+    , "aa aaA"
+    , "aa a aaa"
+    , "aa a a "
+    , "aa a  a"
+    , "aa a b"
+    , "aa abaa"
+    , "aa ab "
+    , "aa aAa"
+    , "aa ac"
+    , "aa  aaaa"
+    , "aa  aa "
+    , "aa  a a"
+    , "aa  ab"
+    , "aa   aa"
+    , "aa    "
+    , "aa  ba"
+    , "aa  A"
+    , "aa baaa"
+    , "aa ba "
+    , "aa b a"
+    , "aa bb"
+    , "aa Aaa"
+    , "aa A "
+    , "aa ca"
+    , "aa \n"
+    , "aabaaaaa"
+    , "aabaaa "
+    , "aabaa a"
+    , "aabaab"
+    , "aaba aa"
+    , "aaba  "
+    , "aababa"
+    , "aabaA"
+    , "aab aaa"
+    , "aab a "
+    , "aab  a"
+    , "aab b"
+    , "aabbaa"
+    , "aabb "
+    , "aabAa"
+    , "aabc"
+    , "aaAaaaa"
+    , "aaAaa "
+    , "aaAa a"
+    , "aaAab"
+    , "aaA aa"
+    , "aaA  "
+    , "aaAba"
+    , "aaAA"
+    , "aacaaa"
+    , "aaca "
+    , "aac a"
+    , "aacb"
+    , "aa\naa"
+    , "aa\n "
+    , "aada"
+    , "aa0"
+    , "a aaaaaaa"
+    , "a aaaaa "
+    , "a aaaa a"
+    , "a aaaab"
+    , "a aaa aa"
+    , "a aaa  "
+    , "a aaaba"
+    , "a aaaA"
+    , "a aa aaa"
+    , "a aa a "
+    , "a aa  a"
+    , "a aa b"
+    , "a aabaa"
+    , "a aab "
+    , "a aaAa"
+    , "a aac"
+    , "a a aaaa"
+    , "a a aa "
+    , "a a a a"
+    , "a a ab"
+    , "a a  aa"
+    , "a a   "
+    , "a a ba"
+    , "a a A"
+    , "a abaaa"
+    , "a aba "
+    , "a ab a"
+    , "a abb"
+    , "a aAaa"
+    , "a aA "
+    , "a aca"
+    , "a a\n"
+    , "a  aaaaa"
+    , "a  aaa "
+    , "a  aa a"
+    , "a  aab"
+    , "a  a aa"
+    , "a  a  "
+    , "a  aba"
+    , "a  aA"
+    , "a   aaa"
+    , "a   a "
+    , "a    a"
+    , "a   b"
+    , "a  baa"
+    , "a  b "
+    , "a  Aa"
+    , "a  c"
+    , "a baaaa"
+    , "a baa "
+    , "a ba a"
+    , "a bab"
+    , "a b aa"
+    , "a b  "
+    , "a bba"
+    , "a bA"
+    , "a Aaaa"
+    , "a Aa "
+    , "a A a"
+    , "a Ab"
+    , "a caa"
+    , "a c "
+    , "a \na"
+    , "a d"
+    , "abaaaaaa"
+    , "abaaaa "
+    , "abaaa a"
+    , "abaaab"
+    , "abaa aa"
+    , "abaa  "
+    , "abaaba"
+    , "abaaA"
+    , "aba aaa"
+    , "aba a "
+    , "aba  a"
+    , "aba b"
+    , "ababaa"
+    , "abab "
+    , "abaAa"
+    , "abac"
+    , "ab aaaa"
+    , "ab aa "
+    , "ab a a"
+    , "ab ab"
+    , "ab  aa"
+    , "ab   "
+    , "ab ba"
+    , "ab A"
+    , "abbaaa"
+    , "abba "
+    , "abb a"
+    , "abbb"
+    , "abAaa"
+    , "abA "
+    , "abca"
+    , "ab\n"
+    , "aAaaaaa"
+    , "aAaaa "
+    , "aAaa a"
+    , "aAaab"
+    , "aAa aa"
+    , "aAa  "
+    , "aAaba"
+    , "aAaA"
+    , "aA aaa"
+    , "aA a "
+    , "aA  a"
+    , "aA b"
+    , "aAbaa"
+    , "aAb "
+    , "aAAa"
+    , "aAc"
+    , "acaaaa"
+    , "acaa "
+    , "aca a"
+    , "acab"
+    , "ac aa"
+    , "ac  "
+    , "acba"
+    , "acA"
+    , "a\naaa"
+    , "a\na "
+    , "a\n a"
+    , "a\nb"
+    , "adaa"
+    , "ad "
+    , "a0a"
+    , "ae"
+    , " aaaaaaaa"
+    , " aaaaaa "
+    , " aaaaa a"
+    , " aaaaab"
+    , " aaaa aa"
+    , " aaaa  "
+    , " aaaaba"
+    , " aaaaA"
+    , " aaa aaa"
+    , " aaa a "
+    , " aaa  a"
+    , " aaa b"
+    , " aaabaa"
+    , " aaab "
+    , " aaaAa"
+    , " aaac"
+    , " aa aaaa"
+    , " aa aa "
+    , " aa a a"
+    , " aa ab"
+    , " aa  aa"
+    , " aa   "
+    , " aa ba"
+    , " aa A"
+    , " aabaaa"
+    , " aaba "
+    , " aab a"
+    , " aabb"
+    , " aaAaa"
+    , " aaA "
+    , " aaca"
+    , " aa\n"
+    , " a aaaaa"
+    , " a aaa "
+    , " a aa a"
+    , " a aab"
+    , " a a aa"
+    , " a a  "
+    , " a aba"
+    , " a aA"
+    , " a  aaa"
+    , " a  a "
+    , " a   a"
+    , " a  b"
+    , " a baa"
+    , " a b "
+    , " a Aa"
+    , " a c"
+    , " abaaaa"
+    , " abaa "
+    , " aba a"
+    , " abab"
+    , " ab aa"
+    , " ab  "
+    , " abba"
+    , " abA"
+    , " aAaaa"
+    , " aAa "
+    , " aA a"
+    , " aAb"
+    , " acaa"
+    , " ac "
+    , " a\na"
+    , " ad"
+    , "  aaaaaa"
+    , "  aaaa "
+    , "  aaa a"
+    , "  aaab"
+    , "  aa aa"
+    , "  aa  "
+    , "  aaba"
+    , "  aaA"
+    , "  a aaa"
+    , "  a a "
+    , "  a  a"
+    , "  a b"
+    , "  abaa"
+    , "  ab "
+    , "  aAa"
+    , "  ac"
+    , "   aaaa"
+    , "   aa "
+    , "   a a"
+    , "   ab"
+    , "    aa"
+    , "     "
+    , "   ba"
+    , "   A"
+    , "  baaa"
+    , "  ba "
+    , "  b a"
+    , "  bb"
+    , "  Aaa"
+    , "  A "
+    , "  ca"
+    , "  \n"
+    , " baaaaa"
+    , " baaa "
+    , " baa a"
+    , " baab"
+    , " ba aa"
+    , " ba  "
+    , " baba"
+    , " baA"
+    , " b aaa"
+    , " b a "
+    , " b  a"
+    , " b b"
+    , " bbaa"
+    , " bb "
+    , " bAa"
+    , " bc"
+    , " Aaaaa"
+    , " Aaa "
+    , " Aa a"
+    , " Aab"
+    , " A aa"
+    , " A  "
+    , " Aba"
+    , " AA"
+    , " caaa"
+    , " ca "
+    , " c a"
+    , " cb"
+    , " \naa"
+    , " \n "
+    , " da"
+    , " 0"
+    , "baaaaaaa"
+    , "baaaaa "
+    , "baaaa a"
+    , "baaaab"
+    , "baaa aa"
+    , "baaa  "
+    , "baaaba"
+    , "baaaA"
+    , "baa aaa"
+    , "baa a "
+    , "baa  a"
+    , "baa b"
+    , "baabaa"
+    , "baab "
+    , "baaAa"
+    , "baac"
+    , "ba aaaa"
+    , "ba aa "
+    , "ba a a"
+    , "ba ab"
+    , "ba  aa"
+    , "ba   "
+    , "ba ba"
+    , "ba A"
+    , "babaaa"
+    , "baba "
+    , "bab a"
+    , "babb"
+    , "baAaa"
+    , "baA "
+    , "baca"
+    , "ba\n"
+    , "b aaaaa"
+    , "b aaa "
+    , "b aa a"
+    , "b aab"
+    , "b a aa"
+    , "b a  "
+    , "b aba"
+    , "b aA"
+    , "b  aaa"
+    , "b  a "
+    , "b   a"
+    , "b  b"
+    , "b baa"
+    , "b b "
+    , "b Aa"
+    , "b c"
+    , "bbaaaa"
+    , "bbaa "
+    , "bba a"
+    , "bbab"
+    , "bb aa"
+    , "bb  "
+    , "bbba"
+    , "bbA"
+    , "bAaaa"
+    , "bAa "
+    , "bA a"
+    , "bAb"
+    , "bcaa"
+    , "bc "
+    , "b\na"
+    , "bd"
+    , "Aaaaaaa"
+    , "Aaaaa "
+    , "Aaaa a"
+    , "Aaaab"
+    , "Aaa aa"
+    , "Aaa  "
+    , "Aaaba"
+    , "AaaA"
+    , "Aa aaa"
+    , "Aa a "
+    , "Aa  a"
+    , "Aa b"
+    , "Aabaa"
+    , "Aab "
+    , "AaAa"
+    , "Aac"
+    , "A aaaa"
+    , "A aa "
+    , "A a a"
+    , "A ab"
+    , "A  aa"
+    , "A   "
+    , "A ba"
+    , "A A"
+    , "Abaaa"
+    , "Aba "
+    , "Ab a"
+    , "Abb"
+    , "AAaa"
+    , "AA "
+    , "Aca"
+    , "A\n"
+    , "caaaaa"
+    , "caaa "
+    , "caa a"
+    , "caab"
+    , "ca aa"
+    , "ca  "
+    , "caba"
+    , "caA"
+    , "c aaa"
+    , "c a "
+    , "c  a"
+    , "c b"
+    , "cbaa"
+    , "cb "
+    , "cAa"
+    , "cc"
+    , "\naaaa"
+    , "\naa "
+    , "\na a"
+    , "\nab"
+    , "\n aa"
+    , "\n  "
+    , "\nba"
+    , "\nA"
+    , "daaa"
+    , "da "
+    , "d a"
+    , "db"
+    , "0aa"
+    , "0 "
+    , "ea"
+    , "B"
+    ]
+  , ...
+  ]
diff --git a/test/main.hs b/test/main.hs
new file mode 100644
--- /dev/null
+++ b/test/main.hs
@@ -0,0 +1,35 @@
+-- Copyright (c) 2015-2018 Rudy Matela.
+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
+import System.Exit (exitFailure)
+import Data.List (elemIndices)
+import qualified Data.Text as T
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+import Numeric.Natural
+
+import Test.LeanCheck
+import Test.LeanCheck.Instances
+
+main :: IO ()
+main =
+  case elemIndices False (tests 1000) of
+  [] -> putStrLn "Tests passed!"
+  is -> putStrLn ("Failed tests:" ++ show is) >> exitFailure
+
+tests :: Int -> [Bool]
+tests n =
+  [ True
+
+  , fails n $ \ts -> T.words (T.unwords ts) == ts
+  , fails n $ \t ->   T.unwords (T.words t) == t
+  , holds n $ \ts ->   T.words (T.unwords (T.words ts)) == T.words ts
+
+  , holds n $ \x y -> x + y == y + (x :: Natural)
+  , fails n $ \x y -> x + y == (x :: Natural)
+
+  , fails n $ \bs -> BS.reverse bs == bs
+  , holds n $ \bs -> BS.reverse (BS.reverse bs) == bs
+
+  , fails n $ \bs -> BL.reverse bs == bs
+  , holds n $ \bs -> BL.reverse (BL.reverse bs) == bs
+  ]
diff --git a/test/sdist b/test/sdist
new file mode 100644
--- /dev/null
+++ b/test/sdist
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# test/sdist: tests the package generated by "cabal sdist".
+#
+# Copyright (c) 2015-2018 Rudy Matela.
+# Distributed under the 3-Clause BSD licence.
+export LC_ALL=C  # consistent sort
+pkgver=` cat *.cabal | grep "^version:" | sed -e "s/version: *//"`
+pkgname=`cat *.cabal | grep "^name:"    | sed -e "s/name: *//"`
+pkg=$pkgname-$pkgver
+set -x
+cabal sdist &&
+cd dist &&
+tar -tf $pkg.tar.gz | sort --ignore-case          > ls-cabal-i  &&
+tar -tf $pkg.tar.gz | sort --ignore-case --unique > ls-cabal-iu &&
+diff -rud ls-cabal-i ls-cabal-iu &&
+rm -f ls-cabal ls-cabal-ignore-case &&
+if [ -d ../.git ]
+then
+	# on git repo, test if files are the same
+	git -C .. ls-files                                      | sort > ls-git   &&
+	tar -tf $pkg.tar.gz | grep -v "/$" | sed -e "s,$pkg/,," | sort > ls-cabal &&
+	diff -rud ls-git ls-cabal &&
+	rm -f ls-git ls-cabal
+else
+	# outside of git repo, test build
+	rm -rf $pkg/ &&
+	tar -xzf $pkg.tar.gz &&
+	cd $pkg/ &&
+	cabal configure --enable-tests --enable-benchmarks &&
+	cabal build &&
+	cabal test
+fi
diff --git a/test/text.hs b/test/text.hs
new file mode 100644
--- /dev/null
+++ b/test/text.hs
@@ -0,0 +1,31 @@
+-- Copyright (c) 2015-2018 Rudy Matela.
+-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
+import System.Exit (exitFailure)
+import Data.List (elemIndices)
+import Data.Text
+
+import Test.LeanCheck
+import Test.LeanCheck.Instances
+import Prelude hiding (lines, unlines, words, unwords)
+
+main :: IO ()
+main =
+  case elemIndices False (tests 1000) of
+  [] -> putStrLn "Tests passed!"
+  is -> putStrLn ("Failed tests:" ++ show is) >> exitFailure
+
+tests :: Int -> [Bool]
+tests n =
+  [ True
+  , fails n $ \ts -> lines (unlines ts) == ts
+  , fails n $ \t ->   unlines (lines t) == t
+  , holds n $ \ts -> unlines (lines (unlines ts)) == unlines ts
+  , holds n $ \ts ->   lines (unlines (lines ts)) == lines ts
+
+  , fails n $ \ts -> words (unwords ts) == ts
+  , fails n $ \t ->   unwords (words t) == t
+  , holds n $ \ts ->   words (unwords (words ts)) == words ts
+
+  , counterExample n (\ts -> words (unwords ts) == ts)
+    == Just ["[\"\"]"]
+  ]
