diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,17 @@
+1.0.4
+=====
+
+* [#53](https://github.com/serokell/universum/issues/53):
+  Add `doctest` to `universum`. Also imporove and fix documentation.
+* [#117](https://github.com/serokell/universum/issues/117):
+  Drop the support of `GHC-8.0.1`.
+* [#104](https://github.com/serokell/universum/issues/104):
+  Reexport `hashWithSalt` from `Data.Hashable`.
+* [#95](https://github.com/serokell/universum/issues/95):
+  Reexport `Compose` from `Data.Functor.Compose`.
+* [#124](https://github.com/serokell/universum/issues/124):
+  Export methods of class `Exception`.
+
 1.0.3
 =====
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
 =========
 
 [![Build Status](https://travis-ci.org/serokell/universum.svg?branch=master)](https://travis-ci.org/serokell/universum)
+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/serokell/universum?branch=master&svg=true)](https://ci.appveyor.com/project/ChShersh/universum)
 [![Hackage](https://img.shields.io/hackage/v/universum.svg)](https://hackage.haskell.org/package/universum)
 [![Stackage LTS](http://stackage.org/package/universum/badge/lts)](http://stackage.org/lts/package/universum)
 [![Stackage Nightly](http://stackage.org/package/universum/badge/nightly)](http://stackage.org/nightly/package/universum)
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/src/Universum/Applicative.hs b/src/Universum/Applicative.hs
--- a/src/Universum/Applicative.hs
+++ b/src/Universum/Applicative.hs
@@ -12,6 +12,9 @@
 import Control.Applicative (Alternative (..), Applicative (..), Const (..), ZipList (..), liftA2,
                             liftA3, optional, (<**>))
 
+-- $setup
+-- >>> import Universum.Monad (Maybe)
+
 -- | Shorter alias for @pure ()@.
 --
 -- >>> pass :: Maybe ()
diff --git a/src/Universum/Base.hs b/src/Universum/Base.hs
--- a/src/Universum/Base.hs
+++ b/src/Universum/Base.hs
@@ -98,6 +98,9 @@
                   prettyCallStack, prettySrcLoc, withFrozenCallStack)
 #endif
 
+-- $setup
+-- >>> import Universum.Function (const, ($))
+
 -- Pending GHC 8.2 we'll expose these.
 
 {-
@@ -117,11 +120,13 @@
 -- | Stricter version of 'Data.Function.$' operator.
 -- Default Prelude defines this at the toplevel module, so we do as well.
 --
--- >>> const 3 $  undefined
+-- >>> const 3 $ Prelude.undefined
 -- 3
--- >>> const 3 $! undefined
+-- >>> const 3 $! Prelude.undefined
+-- *** Exception: Prelude.undefined
 -- CallStack (from HasCallStack):
 --   error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
+-- ...
 ($!) :: (a -> b) -> a -> b
 f $! x = let !vx = x in f vx
 infixr 0 $!
diff --git a/src/Universum/Bool/Guard.hs b/src/Universum/Bool/Guard.hs
--- a/src/Universum/Bool/Guard.hs
+++ b/src/Universum/Bool/Guard.hs
@@ -9,10 +9,17 @@
 import Universum.Function (flip)
 import Universum.Monad (Monad, MonadPlus, (>>=))
 
+-- $setup
+-- >>> import Universum.Applicative (pure)
+-- >>> import Universum.Bool.Reexport (Bool (..))
+-- >>> import Universum.Function (($))
+-- >>> import Universum.Monad (Maybe (..))
+-- >>> import Universum.Print (putTextLn)
+
 -- | Monadic version of 'when'.
 --
--- >>> whenM (pure False) $ putText "No text :("
--- >>> whenM (pure True)  $ putText "Yes text :)"
+-- >>> whenM (pure False) $ putTextLn "No text :("
+-- >>> whenM (pure True)  $ putTextLn "Yes text :)"
 -- Yes text :)
 -- >>> whenM (Just True) (pure ())
 -- Just ()
@@ -26,16 +33,16 @@
 
 -- | Monadic version of 'unless'.
 --
--- >>> unlessM (pure False) $ putText "No text :("
+-- >>> unlessM (pure False) $ putTextLn "No text :("
 -- No text :(
--- >>> unlessM (pure True) $ putText "Yes text :)"
+-- >>> unlessM (pure True) $ putTextLn "Yes text :)"
 unlessM :: Monad m => m Bool -> m () -> m ()
 unlessM p m = p >>= flip unless m
 {-# INLINE unlessM #-}
 
 -- | Monadic version of @if-then-else@.
 --
--- >>> ifM (pure True) (putText "True text") (putText "False text")
+-- >>> ifM (pure True) (putTextLn "True text") (putTextLn "False text")
 -- True text
 ifM :: Monad m => m Bool -> m a -> m a -> m a
 ifM p x y = p >>= \b -> if b then x else y
@@ -43,14 +50,15 @@
 
 -- | Monadic version of 'guard'. Occasionally useful.
 -- Here some complex but real-life example:
+--
 -- @
---   findSomePath :: IO (Maybe FilePath)
+-- findSomePath :: IO (Maybe FilePath)
 --
---   somePath :: MaybeT IO FilePath
---   somePath = do
---       path <- MaybeT findSomePath
---       guardM $ liftIO $ doesDirectoryExist path
---       return path
+-- somePath :: MaybeT IO FilePath
+-- somePath = do
+--     path <- MaybeT findSomePath
+--     guardM $ liftIO $ doesDirectoryExist path
+--     return path
 -- @
 guardM :: MonadPlus m => m Bool -> m ()
 guardM f = f >>= guard
diff --git a/src/Universum/Container/Class.hs b/src/Universum/Container/Class.hs
--- a/src/Universum/Container/Class.hs
+++ b/src/Universum/Container/Class.hs
@@ -41,8 +41,8 @@
        ) where
 
 import Data.Coerce (Coercible, coerce)
-import Prelude hiding (all, and, any, elem, foldMap, foldl, foldr, mapM_, notElem, or, product,
-                sequence_, sum)
+import Prelude hiding (all, and, any, elem, foldMap, foldl, foldr, mapM_, notElem, null, or,
+                product, sequence_, sum)
 
 import Universum.Applicative (Alternative (..), Const, ZipList, pass)
 import Universum.Base (Constraint, Word8)
@@ -86,6 +86,10 @@
 import qualified Data.Vector.Storable as VS
 import qualified Data.Vector.Unboxed as VU
 
+-- $setup
+-- >>> import Universum.String (Text)
+-- >>> import qualified Data.HashMap.Strict as HashMap
+
 ----------------------------------------------------------------------------
 -- Containers (e.g. tuples aren't containers)
 ----------------------------------------------------------------------------
@@ -228,9 +232,8 @@
     type Val t :: *
 
     -- | Converts the structure to the list of the key-value pairs.
-    -- >>> import qualified Data.HashMap as HashMap
     -- >>> toPairs (HashMap.fromList [('a', "xxx"), ('b', "yyy")])
-    -- [('a', "xxx"), ('b', "yyy")]
+    -- [('a',"xxx"),('b',"yyy")]
     toPairs :: t -> [(Key t, Val t)]
 
     -- | Converts the structure to the list of the keys.
@@ -244,7 +247,7 @@
     -- | Converts the structure to the list of the values.
     --
     -- >>> elems (HashMap.fromList [('a', "xxx"), ('b', "yyy")])
-    -- ["xxx", "yyy"]
+    -- ["xxx","yyy"]
     elems :: t -> [Val t]
     elems = map snd . toPairs
     {-# INLINE elems #-}
@@ -591,27 +594,53 @@
 -- Derivative functions
 ----------------------------------------------------------------------------
 
+-- TODO: I should put different strings for different versions but I'm too lazy to do it...
+
+#if MIN_VERSION_base(4,10,1)
 -- | Stricter version of 'Prelude.sum'.
 --
 -- >>> sum [1..10]
 -- 55
 -- >>> sum (Just 3)
--- <interactive>:43:1: error:
+-- ...
 --     • Do not use 'Foldable' methods on Maybe
---     • In the expression: sum (Just 3)
---       In an equation for ‘it’: it = sum (Just 3)
+--       Suggestions:
+--           Instead of
+--               for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
+--           use
+--               whenJust  :: Applicative f => Maybe a    -> (a -> f ()) -> f ()
+--               whenRight :: Applicative f => Either l r -> (r -> f ()) -> f ()
+-- ...
+--           Instead of
+--               fold :: (Foldable t, Monoid m) => t m -> m
+--           use
+--               maybeToMonoid :: Monoid m => Maybe m -> m
+-- ...
+#endif
 sum :: (Container t, Num (Element t)) => t -> Element t
 sum = foldl' (+) 0
 
+#if MIN_VERSION_base(4,10,1)
 -- | Stricter version of 'Prelude.product'.
 --
 -- >>> product [1..10]
 -- 3628800
 -- >>> product (Right 3)
--- <interactive>:45:1: error:
+-- ...
 --     • Do not use 'Foldable' methods on Either
---     • In the expression: product (Right 3)
---       In an equation for ‘it’: it = product (Right 3)
+--       Suggestions:
+--           Instead of
+--               for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
+--           use
+--               whenJust  :: Applicative f => Maybe a    -> (a -> f ()) -> f ()
+--               whenRight :: Applicative f => Either l r -> (r -> f ()) -> f ()
+-- ...
+--           Instead of
+--               fold :: (Foldable t, Monoid m) => t m -> m
+--           use
+--               maybeToMonoid :: Monoid m => Maybe m -> m
+-- ...
+#endif
 product :: (Container t, Num (Element t)) => t -> Element t
 product = foldl' (*) 1
 
diff --git a/src/Universum/Container/Reexport.hs b/src/Universum/Container/Reexport.hs
--- a/src/Universum/Container/Reexport.hs
+++ b/src/Universum/Container/Reexport.hs
@@ -13,7 +13,7 @@
        , module Data.Vector
        ) where
 
-import Data.Hashable (Hashable)
+import Data.Hashable (Hashable (hashWithSalt))
 import Data.HashMap.Strict (HashMap)
 import Data.HashSet (HashSet)
 import Data.IntMap.Strict (IntMap)
diff --git a/src/Universum/Exception.hs b/src/Universum/Exception.hs
--- a/src/Universum/Exception.hs
+++ b/src/Universum/Exception.hs
@@ -15,7 +15,7 @@
        ) where
 
 -- exceptions from safe-exceptions
-import Control.Exception.Safe (Exception, MonadCatch, MonadMask (..), MonadThrow,
+import Control.Exception.Safe (Exception (..), MonadCatch, MonadMask (..), MonadThrow,
                                SomeException (..), bracket, bracketOnError, bracket_, catch,
                                catchAny, displayException, finally, handleAny, mask_, onException,
                                throwM, try, tryAny)
diff --git a/src/Universum/Functor/Fmap.hs b/src/Universum/Functor/Fmap.hs
--- a/src/Universum/Functor/Fmap.hs
+++ b/src/Universum/Functor/Fmap.hs
@@ -12,6 +12,10 @@
 map :: Functor f => (a -> b) -> f a -> f b
 map = fmap
 
+-- $setup
+-- >>> import Universum.Base (negate)
+-- >>> import Universum.Monad (Maybe (..))
+
 -- | Alias for @fmap . fmap@. Convenient to work with two nested 'Functor's.
 --
 -- >>> negate <<$>> Just [1,2,3]
diff --git a/src/Universum/Functor/Reexport.hs b/src/Universum/Functor/Reexport.hs
--- a/src/Universum/Functor/Reexport.hs
+++ b/src/Universum/Functor/Reexport.hs
@@ -4,10 +4,12 @@
        ( module Control.Arrow
        , module Data.Bifunctor
        , module Data.Functor
+       , module Data.Functor.Compose
        , module Data.Functor.Identity
        ) where
 
 import Control.Arrow ((&&&))
 import Data.Bifunctor (Bifunctor (..))
 import Data.Functor (Functor (..), void, ($>), (<$>))
+import Data.Functor.Compose (Compose (..))
 import Data.Functor.Identity (Identity (..))
diff --git a/src/Universum/List/Safe.hs b/src/Universum/List/Safe.hs
--- a/src/Universum/List/Safe.hs
+++ b/src/Universum/List/Safe.hs
@@ -19,6 +19,13 @@
 import Universum.Functor (fmap)
 import Universum.Monad (Maybe (..))
 
+-- $setup
+-- >>> import Universum.Applicative (pure)
+-- >>> import Universum.Base ((==), even)
+-- >>> import Universum.Bool (Bool (..))
+-- >>> import Universum.Container (length)
+-- >>> import Universum.Function (($))
+
 -- | Returns default list if given list is empty.
 -- Otherwise applies given function to every element.
 --
diff --git a/src/Universum/Monad/Container.hs b/src/Universum/Monad/Container.hs
--- a/src/Universum/Monad/Container.hs
+++ b/src/Universum/Monad/Container.hs
@@ -20,19 +20,26 @@
 import Universum.Functor (fmap)
 import Universum.Monad.Reexport (Monad (..))
 
+-- $setup
+-- :set -XOverloadedStrings
+-- >>> import Universum.Base (even)
+-- >>> import Universum.Monad (Maybe (..), (>=>))
+-- >>> import Universum.Print (putTextLn)
+-- >>> import Universum.String (readMaybe)
+
 -- | Lifting bind into a monad. Generalized version of @concatMap@
 -- that works with a monadic predicate. Old and simpler specialized to list
 -- version had next type:
 --
 -- @
---     concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
+-- concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
 -- @
 --
 -- Side note: previously it had type
 --
 -- @
---     concatMapM :: (Applicative q, Monad m, Traversable m)
---                => (a -> q (m b)) -> m a -> q (m b)
+-- concatMapM :: (Applicative q, Monad m, Traversable m)
+--            => (a -> q (m b)) -> m a -> q (m b)
 -- @
 --
 -- Such signature didn't allow to use this function when traversed container
@@ -40,7 +47,7 @@
 -- Now you can use it like e.g.
 --
 -- @
---     concatMapM readFile files >>= putStrLn
+-- concatMapM readFile files >>= putTextLn
 -- @
 concatMapM
     :: ( Applicative f
@@ -76,7 +83,7 @@
 -- Just False
 -- >>> andM [Just True, Nothing]
 -- Nothing
--- >>> andM [putStrLn "1" >> pure True, putStrLn "2" >> pure False, putStrLn "3" >> undefined]
+-- >>> andM [putTextLn "1" >> pure True, putTextLn "2" >> pure False, putTextLn "3" >> pure True]
 -- 1
 -- 2
 -- False
diff --git a/src/Universum/Monad/Either.hs b/src/Universum/Monad/Either.hs
--- a/src/Universum/Monad/Either.hs
+++ b/src/Universum/Monad/Either.hs
@@ -23,6 +23,8 @@
 import Universum.Applicative (pass)
 import Universum.Monad.Reexport (Either (..), either)
 
+-- $setup
+-- >>> import Universum.Bool (Bool (..))
 
 -- | Extracts value from 'Left' or return given default value.
 --
@@ -57,7 +59,7 @@
 --
 -- >>> rightToMaybe (Left True)
 -- Nothing
--- >>> leftToMaybe (Right "aba")
+-- >>> rightToMaybe (Right "aba")
 -- Just "aba"
 rightToMaybe :: Either l r -> Maybe r
 rightToMaybe = either (const Nothing) Just
@@ -75,7 +77,7 @@
 --
 -- >>> maybeToLeft True (Just "aba")
 -- Left "aba"
--- >>> maybeToRight True Nothing
+-- >>> maybeToLeft True Nothing
 -- Right True
 maybeToLeft :: r -> Maybe l -> Either l r
 maybeToLeft r = maybe (Right r) Left
diff --git a/src/Universum/Monad/Maybe.hs b/src/Universum/Monad/Maybe.hs
--- a/src/Universum/Monad/Maybe.hs
+++ b/src/Universum/Monad/Maybe.hs
@@ -14,6 +14,11 @@
 import Universum.Applicative (Applicative, pass, pure)
 import Universum.Monad.Reexport (Maybe (..), Monad (..))
 
+-- $setup
+-- >>> import Universum.Bool (Bool (..))
+-- >>> import Universum.Function (($))
+-- >>> import Universum.Print (putTextLn)
+
 -- | Specialized version of 'for_' for 'Maybe'. It's used for code readability.
 -- Also helps to avoid space leaks:
 -- <http://www.snoyman.com/blog/2017/01/foldable-mapm-maybe-and-recursive-functions Foldable.mapM_ space leak>.
@@ -42,9 +47,9 @@
 -- | Performs default 'Applicative' action if 'Nothing' is given.
 -- Do nothing for 'Just'. Convenient for discarding 'Just' content.
 --
--- >>> whenNothing_ Nothing $ putText "Nothing!"
+-- >>> whenNothing_ Nothing $ putTextLn "Nothing!"
 -- Nothing!
--- >>> whenNothing_ (Just True) $ putText "Nothing!"
+-- >>> whenNothing_ (Just True) $ putTextLn "Nothing!"
 whenNothing_ :: Applicative f => Maybe a -> f () -> f ()
 whenNothing_ Nothing m = m
 whenNothing_ _       _ = pass
diff --git a/src/Universum/Monoid.hs b/src/Universum/Monoid.hs
--- a/src/Universum/Monoid.hs
+++ b/src/Universum/Monoid.hs
@@ -23,6 +23,10 @@
 
 import Universum.Monad.Reexport (Maybe, fromMaybe)
 
+-- $setup
+-- >>> import Universum.Base (Int)
+-- >>> import Universum.Monad (Maybe (..))
+
 -- | Extracts 'Monoid' value from 'Maybe' returning 'mempty' if 'Nothing'.
 --
 -- >>> maybeToMonoid (Just [1,2,3] :: Maybe [Int])
diff --git a/src/Universum/Nub.hs b/src/Universum/Nub.hs
--- a/src/Universum/Nub.hs
+++ b/src/Universum/Nub.hs
@@ -39,7 +39,7 @@
 -- | Like 'Prelude.nub' but runs in @O(n * log n)@ time and requires 'Ord'.
 --
 -- >>> ordNub [3, 3, 3, 2, 2, -1, 1]
--- [3, 2, -1, 1]
+-- [3,2,-1,1]
 ordNub :: (Ord a) => [a] -> [a]
 ordNub = go Set.empty
   where
@@ -52,7 +52,7 @@
 -- | Like 'Prelude.nub' but runs in @O(n * log_16(n))@ time and requires 'Hashable'.
 --
 -- >>> hashNub [3, 3, 3, 2, 2, -1, 1]
--- [3, 2, -1, 1]
+-- [3,2,-1,1]
 hashNub :: (Eq a, Hashable a) => [a] -> [a]
 hashNub = go HashSet.empty
   where
@@ -65,13 +65,13 @@
 -- | Like 'ordNub' but also sorts a list.
 --
 -- >>> sortNub [3, 3, 3, 2, 2, -1, 1]
--- [-1, 1, 2, 3]
+-- [-1,1,2,3]
 sortNub :: (Ord a) => [a] -> [a]
 sortNub = Set.toList . Set.fromList
 
 -- | Like 'hashNub' but has better performance and also doesn't save the order.
 --
 -- >>> unstableNub [3, 3, 3, 2, 2, -1, 1]
--- [1, 2, 3, -1]
+-- [1,2,3,-1]
 unstableNub :: (Eq a, Hashable a) => [a] -> [a]
 unstableNub = HashSet.toList . HashSet.fromList
diff --git a/src/Universum/String/Conversion.hs b/src/Universum/String/Conversion.hs
--- a/src/Universum/String/Conversion.hs
+++ b/src/Universum/String/Conversion.hs
@@ -44,6 +44,12 @@
 
 import qualified GHC.Show as Show (Show (show))
 
+-- $setup
+-- >>> :set -XTypeApplications -XOverloadedStrings
+-- >>> import Universum.Base (Int)
+-- >>> import Universum.Function (($))
+-- >>> import Universum.Print (putStrLn)
+
 -- | Type synonym for 'Data.Text.Lazy.Text'.
 type LText = LT.Text
 
diff --git a/src/Universum/VarArg.hs b/src/Universum/VarArg.hs
--- a/src/Universum/VarArg.hs
+++ b/src/Universum/VarArg.hs
@@ -11,6 +11,12 @@
        ( SuperComposition(..)
        ) where
 
+-- $setup
+-- >>> import Universum.Base ((+))
+-- >>> import Universum.Container (null)
+-- >>> import Prelude (show)
+-- >>> import Data.List (zip5)
+
 class SuperComposition a b c | a b -> c where
     -- | Allows to apply function to result of another function with multiple
     -- arguments.
diff --git a/test/Doctest.hs b/test/Doctest.hs
new file mode 100644
--- /dev/null
+++ b/test/Doctest.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE CPP #-}
+
+module Main (main) where
+
+#if defined(mingw32_HOST_OS) || __GLASGOW_HASKELL__ < 802
+
+main :: IO ()
+main = return ()
+
+#else
+
+import System.FilePath.Glob (glob)
+import Test.DocTest (doctest)
+
+main :: IO ()
+main = do
+    sourceFiles <- glob "src/**/*.hs"
+    doctest $ "-XNoImplicitPrelude" : sourceFiles
+
+#endif
diff --git a/universum.cabal b/universum.cabal
--- a/universum.cabal
+++ b/universum.cabal
@@ -1,20 +1,20 @@
 name: universum
-version: 1.0.3
+version: 1.0.4
 cabal-version: >=1.18
 build-type: Simple
 license: MIT
 license-file: LICENSE
-copyright: 2016 Stephen Diehl, 2016-2017 Serokell
+copyright: 2016 Stephen Diehl, 2016-2018 Serokell
 maintainer: Serokell <hi@serokell.io>
 stability: stable
 homepage: https://github.com/serokell/universum
 bug-reports: https://github.com/serokell/universum/issues
 synopsis: Custom prelude used in Serokell
 description:
-    Custom prelude used in Serokell
+    See README.md file for more details.
 category: Prelude
 author: Stephen Diehl, @serokell
-tested-with: GHC ==7.10.3 GHC ==8.0.1 GHC ==8.0.2 GHC ==8.2.2
+tested-with: GHC ==7.10.3 GHC ==8.0.2 GHC ==8.2.2
 extra-doc-files: CHANGES.md
                  README.md
 
@@ -65,10 +65,10 @@
         Universum.VarArg
     build-depends:
         base >=4.8 && <5,
-        bytestring >=0.10.8.2,
-        containers >=0.5.10.2,
-        deepseq >=1.4.3.0,
-        ghc-prim >=0.5.1.1,
+        bytestring >=0.10.8.1,
+        containers >=0.5.7.1,
+        deepseq >=1.4.2.0,
+        ghc-prim >=0.4.0.0,
         hashable >=1.2.6.1,
         microlens >=0.4.8.1,
         microlens-mtl >=0.1.11.0,
@@ -87,16 +87,26 @@
     hs-source-dirs: src
     ghc-options: -Wall -fwarn-implicit-prelude
 
+test-suite  universum-doctest
+    type: exitcode-stdio-1.0
+    main-is: Doctest.hs
+    build-depends:
+        base >=4.8 && <5,
+        doctest >=0.11.4,
+        Glob >=0.8.0
+    default-language: Haskell2010
+    hs-source-dirs: test
+    ghc-options: -threaded
 
 benchmark  universum-benchmark
     type: exitcode-stdio-1.0
     main-is: Main.hs
     build-depends:
-        base >=4.10.1.0 && <5,
+        base >=4.9.1.0 && <5,
         universum -any,
-        containers >=0.5.10.2,
-        criterion >=1.2.6.0,
-        deepseq >=1.4.3.0,
+        containers >=0.5.7.1,
+        criterion >=1.1.4.0,
+        deepseq >=1.4.2.0,
         hashable >=1.2.6.1,
         mtl >=2.2.1,
         semigroups >=0.18.3,
