diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,9 @@
+# Changelog for rio
+
+## 0.1.0.0
+
+* Initial stable release
+
 ## 0.0
 
 __NOTE__ All releases beginning with 0.0 are considered
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -106,6 +106,11 @@
   recommended qualified names in the modules themselves. For example,
   `import qualified RIO.ByteString as B`. See the module documentation
   for more information.
+* Infix operators may be imported unqualified, with a separate import
+  line if necessary. For example, `import RIO.Map ((?!), (\\))`. Do
+  this only if your module contains no overlapping infix names,
+  regardless of qualification. For instance, if you are importing both
+  `RIO.Map.\\` and `RIO.List.\\` do not import either one unqualified.
 
 __TODO__ In the future, we may have editor integration or external
 tooling to help with import management. Also, see project template
@@ -326,6 +331,25 @@
   exceptions.
 * Do all resource allocations with functions like `bracket` and
   `finally`.
+
+It’s a good idea to define an app-wide exception type:
+
+```haskell
+data AppExceptions
+  = NetworkChangeError Text
+  | FilePathError FilePath
+  | ImpossibleError
+  deriving (Typeable)
+
+instance Exception AppExceptions
+
+instance Show AppExceptions where
+  show =
+    \case
+      NetworkChangeError err -> "network error: " <> (unpack err)
+      FilePathError fp -> "error accessing filepath at: " <> fp
+      ImpossibleError -> "this codepath should never have been executed. Please report a bug."
+```
 
 ### Strict data fields
 
diff --git a/rio.cabal b/rio.cabal
--- a/rio.cabal
+++ b/rio.cabal
@@ -1,13 +1,13 @@
--- This file has been generated from package.yaml by hpack version 0.21.2.
+-- This file has been generated from package.yaml by hpack version 0.28.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 03ea77dc722a584f48bb591def1080ab6f6e2d687ff376c32027b008640c377e
+-- hash: fbb7c4b9567f7b9802c00b874f404950b8358f767ddc06a21b77c66e3e4cfabd
 
 name:           rio
-version:        0.0.3.0
+version:        0.1.0.0
 synopsis:       A standard library for Haskell
-description:    Work in progress library, see README at <https://github.com/commercialhaskell/rio#readme>
+description:    See README and Haddocks at <https://www.stackage.org/package/rio>
 category:       Control
 homepage:       https://github.com/commercialhaskell/rio#readme
 bug-reports:    https://github.com/commercialhaskell/rio/issues
@@ -17,7 +17,6 @@
 license-file:   LICENSE
 build-type:     Simple
 cabal-version:  >= 1.10
-
 extra-source-files:
     ChangeLog.md
     README.md
@@ -27,6 +26,58 @@
   location: https://github.com/commercialhaskell/rio
 
 library
+  exposed-modules:
+      RIO
+      RIO.ByteString
+      RIO.ByteString.Lazy
+      RIO.ByteString.Lazy.Partial
+      RIO.ByteString.Partial
+      RIO.Char
+      RIO.Char.Partial
+      RIO.Directory
+      RIO.FilePath
+      RIO.HashMap
+      RIO.HashMap.Partial
+      RIO.HashSet
+      RIO.List
+      RIO.List.Partial
+      RIO.Map
+      RIO.Map.Partial
+      RIO.Map.Unchecked
+      RIO.Process
+      RIO.Seq
+      RIO.Set
+      RIO.Set.Partial
+      RIO.Set.Unchecked
+      RIO.Text
+      RIO.Text.Lazy
+      RIO.Text.Lazy.Partial
+      RIO.Text.Partial
+      RIO.Time
+      RIO.Vector
+      RIO.Vector.Boxed
+      RIO.Vector.Boxed.Partial
+      RIO.Vector.Boxed.Unsafe
+      RIO.Vector.Partial
+      RIO.Vector.Storable
+      RIO.Vector.Storable.Partial
+      RIO.Vector.Storable.Unsafe
+      RIO.Vector.Unboxed
+      RIO.Vector.Unboxed.Partial
+      RIO.Vector.Unboxed.Unsafe
+      RIO.Vector.Unsafe
+  other-modules:
+      RIO.Prelude.Display
+      RIO.Prelude.Extra
+      RIO.Prelude.IO
+      RIO.Prelude.Lens
+      RIO.Prelude.Logger
+      RIO.Prelude.Reexports
+      RIO.Prelude.Renames
+      RIO.Prelude.RIO
+      RIO.Prelude.Text
+      RIO.Prelude.Trace
+      RIO.Prelude.URef
   hs-source-dirs:
       src/
   build-depends:
@@ -44,8 +95,8 @@
     , process
     , text
     , time
-    , typed-process >=0.2.1.0
-    , unliftio >=0.2.4.0
+    , typed-process >=0.2.2.0
+    , unliftio >=0.2.6.0
     , unordered-containers
     , vector
   if os(windows)
@@ -55,43 +106,18 @@
   else
     build-depends:
         unix
-  exposed-modules:
-      RIO
-      RIO.ByteString
-      RIO.ByteString.Lazy
-      RIO.Char
-      RIO.Directory
-      RIO.FilePath
-      RIO.HashMap
-      RIO.HashSet
-      RIO.List
-      RIO.Map
-      RIO.Prelude.Display
-      RIO.Prelude.Extra
-      RIO.Prelude.IO
-      RIO.Prelude.Lens
-      RIO.Prelude.Logger
-      RIO.Prelude.Reexports
-      RIO.Prelude.Renames
-      RIO.Prelude.RIO
-      RIO.Prelude.Text
-      RIO.Prelude.URef
-      RIO.Process
-      RIO.Set
-      RIO.Text
-      RIO.Text.Lazy
-      RIO.Time
-      RIO.Vector
-      RIO.Vector.Boxed
-      RIO.Vector.Storable
-      RIO.Vector.Unboxed
-  other-modules:
-      Paths_rio
   default-language: Haskell2010
 
 test-suite spec
   type: exitcode-stdio-1.0
   main-is: Spec.hs
+  other-modules:
+      RIO.ListSpec
+      RIO.LoggerSpec
+      RIO.Prelude.IOSpec
+      RIO.PreludeSpec
+      RIO.TextSpec
+      Paths_rio
   hs-source-dirs:
       test
   build-depends:
@@ -111,8 +137,8 @@
     , rio
     , text
     , time
-    , typed-process >=0.2.1.0
-    , unliftio >=0.2.4.0
+    , typed-process >=0.2.2.0
+    , unliftio >=0.2.6.0
     , unordered-containers
     , vector
   if os(windows)
@@ -122,10 +148,4 @@
   else
     build-depends:
         unix
-  other-modules:
-      RIO.ListSpec
-      RIO.LoggerSpec
-      RIO.PreludeSpec
-      RIO.TextSpec
-      Paths_rio
   default-language: Haskell2010
diff --git a/src/RIO.hs b/src/RIO.hs
--- a/src/RIO.hs
+++ b/src/RIO.hs
@@ -8,6 +8,7 @@
   , module RIO.Prelude.Reexports
   , module RIO.Prelude.Renames
   , module RIO.Prelude.Text
+  , module RIO.Prelude.Trace
   , module RIO.Prelude.URef
   ) where
 
@@ -20,4 +21,5 @@
 import RIO.Prelude.Reexports
 import RIO.Prelude.Renames
 import RIO.Prelude.Text
+import RIO.Prelude.Trace
 import RIO.Prelude.URef
diff --git a/src/RIO/ByteString/Lazy.hs b/src/RIO/ByteString/Lazy.hs
--- a/src/RIO/ByteString/Lazy.hs
+++ b/src/RIO/ByteString/Lazy.hs
@@ -1,8 +1,211 @@
 -- | Lazy @ByteString@. Import as:
 --
--- > import qualified RIO.ByteString.Lazy as B.Lazy
+-- > import qualified RIO.ByteString.Lazy as BL
+{-# LANGUAGE NoImplicitPrelude #-}
 module RIO.ByteString.Lazy
-  ( module Data.ByteString.Lazy
+  (
+  -- * The @ByteString@ type
+    Data.ByteString.Lazy.ByteString
+
+  -- * Introducing and eliminating 'ByteString's
+  , Data.ByteString.Lazy.empty
+  , Data.ByteString.Lazy.singleton
+  , Data.ByteString.Lazy.pack
+  , Data.ByteString.Lazy.unpack
+  , Data.ByteString.Lazy.fromStrict
+  , Data.ByteString.Lazy.toStrict
+  , Data.ByteString.Lazy.fromChunks
+  , Data.ByteString.Lazy.toChunks
+  , Data.ByteString.Lazy.foldrChunks
+  , Data.ByteString.Lazy.foldlChunks
+
+  -- * Basic interface
+  , Data.ByteString.Lazy.cons
+  , Data.ByteString.Lazy.cons'
+  , Data.ByteString.Lazy.snoc
+  , Data.ByteString.Lazy.append
+  , Data.ByteString.Lazy.uncons
+  , Data.ByteString.Lazy.unsnoc
+  , Data.ByteString.Lazy.null
+  , Data.ByteString.Lazy.length
+
+  -- * Transforming ByteStrings
+  , Data.ByteString.Lazy.map
+  , Data.ByteString.Lazy.reverse
+  , Data.ByteString.Lazy.intersperse
+  , Data.ByteString.Lazy.intercalate
+  , Data.ByteString.Lazy.transpose
+
+  -- * Reducing 'ByteString's (folds)
+  , Data.ByteString.Lazy.foldl
+  , Data.ByteString.Lazy.foldl'
+  , Data.ByteString.Lazy.foldr
+
+  -- ** Special folds
+  , Data.ByteString.Lazy.concat
+  , Data.ByteString.Lazy.concatMap
+  , Data.ByteString.Lazy.any
+  , Data.ByteString.Lazy.all
+
+  -- * Building ByteStrings
+  -- ** Scans
+  , Data.ByteString.Lazy.scanl
+
+  -- ** Accumulating maps
+  , Data.ByteString.Lazy.mapAccumL
+  , Data.ByteString.Lazy.mapAccumR
+
+  -- ** Infinite ByteStrings
+  , Data.ByteString.Lazy.repeat
+  , Data.ByteString.Lazy.replicate
+  , Data.ByteString.Lazy.cycle
+  , Data.ByteString.Lazy.iterate
+
+  -- ** Unfolding ByteStrings
+  , Data.ByteString.Lazy.unfoldr
+
+  -- * Substrings
+  -- ** Breaking strings
+  , Data.ByteString.Lazy.take
+  , Data.ByteString.Lazy.drop
+  , Data.ByteString.Lazy.splitAt
+  , Data.ByteString.Lazy.takeWhile
+  , Data.ByteString.Lazy.dropWhile
+  , Data.ByteString.Lazy.span
+  , Data.ByteString.Lazy.break
+  , Data.ByteString.Lazy.group
+  , Data.ByteString.Lazy.groupBy
+  , Data.ByteString.Lazy.inits
+  , Data.ByteString.Lazy.tails
+  , Data.ByteString.Lazy.stripPrefix
+  , Data.ByteString.Lazy.stripSuffix
+
+  -- ** Breaking into many substrings
+  , Data.ByteString.Lazy.split
+  , Data.ByteString.Lazy.splitWith
+
+  -- * Predicates
+  , Data.ByteString.Lazy.isPrefixOf
+  , Data.ByteString.Lazy.isSuffixOf
+
+  -- * Search ByteStrings
+  -- ** Searching by equality
+  , Data.ByteString.Lazy.elem
+  , Data.ByteString.Lazy.notElem
+
+  -- ** Searching with a predicate
+  , Data.ByteString.Lazy.find
+  , Data.ByteString.Lazy.filter
+  , Data.ByteString.Lazy.partition
+
+  -- * Indexing ByteStrings
+  , Data.ByteString.Lazy.index
+  , Data.ByteString.Lazy.elemIndex
+  , Data.ByteString.Lazy.elemIndexEnd
+  , Data.ByteString.Lazy.elemIndices
+  , Data.ByteString.Lazy.findIndex
+  , Data.ByteString.Lazy.findIndices
+  , Data.ByteString.Lazy.count
+
+  -- * Zipping and unzipping ByteStrings
+  , Data.ByteString.Lazy.zip
+  , Data.ByteString.Lazy.zipWith
+  , Data.ByteString.Lazy.unzip
+
+  -- * Low level conversions
+  -- ** Copying ByteStrings
+  , Data.ByteString.Lazy.copy
+
+  -- * I\/O with 'ByteString's
+  -- ** Standard input and output
+  , getContents
+  , putStr
+  , putStrLn
+  , interact
+
+  -- ** Files
+  , readFile
+  , writeFile
+  , appendFile
+
+  -- ** I\/O with Handles
+  , hGetContents
+  , hGet
+  , hGetNonBlocking
+  , hPut
+  , hPutNonBlocking
+  , hPutStr
   ) where
 
-import Data.ByteString.Lazy
+import Data.ByteString.Lazy hiding
+  (
+    getContents
+  , putStr
+  , putStrLn
+  , interact
+  , readFile
+  , writeFile
+  , appendFile
+  , hGetContents
+  , hGet
+  , hGetNonBlocking
+  , hPut
+  , hPutNonBlocking
+  , hPutStr
+  )
+import qualified Data.ByteString.Lazy
+import qualified Data.ByteString.Lazy.Char8
+import RIO
+
+-- | Lifted 'Data.ByteString.Lazy.getContents'
+getContents :: MonadIO m => m LByteString
+getContents = liftIO Data.ByteString.Lazy.getContents
+
+-- | Lifted 'Data.ByteString.Lazy.putStr'
+putStr :: MonadIO m => LByteString -> m ()
+putStr = liftIO . Data.ByteString.Lazy.putStr
+
+-- | Lifted 'Data.ByteString.Lazy.putStrLn'
+putStrLn :: MonadIO m => LByteString -> m ()
+putStrLn = liftIO . Data.ByteString.Lazy.Char8.putStrLn
+
+-- | Lifted 'Data.ByteString.Lazy.interact'
+interact :: MonadIO m => (LByteString -> LByteString) -> m ()
+interact = liftIO . Data.ByteString.Lazy.interact
+
+-- | Lifted 'Data.ByteString.Lazy.readFile'
+readFile :: MonadIO m => FilePath -> m LByteString
+readFile = liftIO . Data.ByteString.Lazy.readFile
+
+-- | Lifted 'Data.ByteString.Lazy.writeFile'
+writeFile :: MonadIO m => FilePath -> LByteString -> m ()
+writeFile fp contents =
+  liftIO $ Data.ByteString.Lazy.writeFile fp contents
+
+-- | Lifted 'Data.ByteString.Lazy.appendFile'
+appendFile :: MonadIO m => FilePath -> LByteString -> m ()
+appendFile fp = liftIO . Data.ByteString.Lazy.appendFile fp
+
+-- | Lifted 'Data.ByteString.Lazy.hGet'
+hGet :: MonadIO m => Handle -> Int -> m LByteString
+hGet handle' count' = liftIO $ Data.ByteString.Lazy.hGet handle' count'
+
+-- | Lifted 'Data.ByteString.Lazy.hGetContents'
+hGetContents :: MonadIO m => Handle -> m LByteString
+hGetContents = liftIO . Data.ByteString.Lazy.hGetContents
+
+-- | Lifted 'Data.ByteString.Lazy.hGetNonBlocking'
+hGetNonBlocking :: MonadIO m => Handle -> Int -> m LByteString
+hGetNonBlocking h = liftIO . Data.ByteString.Lazy.hGetNonBlocking h
+
+-- | Lifted 'Data.ByteString.Lazy.hPut'
+hPut :: MonadIO m => Handle -> LByteString -> m ()
+hPut h = liftIO . Data.ByteString.Lazy.hPut h
+
+-- | Lifted 'Data.ByteString.Lazy.hPutNonBlocking'
+hPutNonBlocking :: MonadIO m => Handle -> LByteString -> m LByteString
+hPutNonBlocking h = liftIO . Data.ByteString.Lazy.hPutNonBlocking h
+
+-- | Lifted 'Data.ByteString.Lazy.hPutStr'
+hPutStr :: MonadIO m => Handle -> LByteString -> m ()
+hPutStr h = liftIO . Data.ByteString.Lazy.hPutStr h
diff --git a/src/RIO/ByteString/Lazy/Partial.hs b/src/RIO/ByteString/Lazy/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/ByteString/Lazy/Partial.hs
@@ -0,0 +1,21 @@
+-- | This module exports all the partial functions from "Data.ByteString.Lazy"
+
+module RIO.ByteString.Lazy.Partial
+  (
+  -- * Basic interface
+    Data.ByteString.Lazy.head
+  , Data.ByteString.Lazy.last
+  , Data.ByteString.Lazy.tail
+  , Data.ByteString.Lazy.init
+
+  -- * Reducing 'ByteString's (folds)
+  , Data.ByteString.Lazy.foldl1
+  , Data.ByteString.Lazy.foldl1'
+  , Data.ByteString.Lazy.foldr1
+
+  -- ** Special folds
+  , Data.ByteString.Lazy.maximum
+  , Data.ByteString.Lazy.minimum
+  ) where
+
+import qualified Data.ByteString.Lazy
diff --git a/src/RIO/ByteString/Partial.hs b/src/RIO/ByteString/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/ByteString/Partial.hs
@@ -0,0 +1,22 @@
+-- | This module exports all the partial functions from 'Data.ByteString'
+
+module RIO.ByteString.Partial
+  (
+  -- * Basic interface
+    Data.ByteString.head
+  , Data.ByteString.last
+  , Data.ByteString.tail
+  , Data.ByteString.init
+
+  -- * Reducing 'ByteString's (folds)
+  , Data.ByteString.foldl1
+  , Data.ByteString.foldl1'
+  , Data.ByteString.foldr1
+  , Data.ByteString.foldr1'
+
+  -- * Special folds
+  , Data.ByteString.maximum
+  , Data.ByteString.minimum
+  ) where
+
+import qualified Data.ByteString
diff --git a/src/RIO/Char.hs b/src/RIO/Char.hs
--- a/src/RIO/Char.hs
+++ b/src/RIO/Char.hs
@@ -2,7 +2,52 @@
 --
 -- > import qualified RIO.Char as C
 module RIO.Char
-  ( module Data.Char
+  (
+    Data.Char.Char
+
+  -- * Character classification
+  -- | Unicode characters are divided into letters, Data.Char.numbers, marks,
+  -- punctuation, Data.Char.symbols, separators (including spaces) and others
+  -- (including control characters).
+  , Data.Char.isControl
+  , Data.Char.isSpace
+  , Data.Char.isLower
+  , Data.Char.isUpper
+  , Data.Char.isAlpha
+  , Data.Char.isAlphaNum
+  , Data.Char.isPrint
+  , Data.Char.isDigit
+  , Data.Char.isOctDigit
+  , Data.Char.isHexDigit
+  , Data.Char.isLetter
+  , Data.Char.isMark
+  , Data.Char.isNumber
+  , Data.Char.isPunctuation
+  , Data.Char.isSymbol
+  , Data.Char.isSeparator
+
+  -- ** Subranges
+  , Data.Char.isAscii
+  , Data.Char.isLatin1
+  , Data.Char.isAsciiUpper
+  , Data.Char.isAsciiLower
+
+  -- ** Unicode general categories
+  , Data.Char.GeneralCategory(..)
+  , Data.Char.generalCategory
+
+  -- * Case conversion
+  , Data.Char.toUpper
+  , Data.Char.toLower
+  , Data.Char.toTitle
+
+  -- * Numeric representations
+  , Data.Char.ord
+
+  -- * String representations
+  , Data.Char.showLitChar
+  , Data.Char.lexLitChar
+  , Data.Char.readLitChar
   ) where
 
-import Data.Char
+import qualified Data.Char
diff --git a/src/RIO/Char/Partial.hs b/src/RIO/Char/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Char/Partial.hs
@@ -0,0 +1,11 @@
+module RIO.Char.Partial
+  (
+  -- * Single digit characters
+    Data.Char.digitToInt
+  , Data.Char.intToDigit
+
+  -- * Numeric representations
+  , Data.Char.chr
+  ) where
+
+import qualified Data.Char
diff --git a/src/RIO/Directory.hs b/src/RIO/Directory.hs
--- a/src/RIO/Directory.hs
+++ b/src/RIO/Directory.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 module RIO.Directory
-  ( module System.Directory
+  ( module UnliftIO.Directory
   ) where
 
-import System.Directory
+import UnliftIO.Directory
diff --git a/src/RIO/FilePath.hs b/src/RIO/FilePath.hs
--- a/src/RIO/FilePath.hs
+++ b/src/RIO/FilePath.hs
@@ -1,5 +1,12 @@
 module RIO.FilePath
   ( module System.FilePath
+  , getSearchPath
   ) where
 
-import System.FilePath
+import Control.Monad.IO.Class
+import System.FilePath hiding(getSearchPath)
+import qualified System.FilePath
+
+-- | Lifted version of 'System.FilePath.getSearchPath'
+getSearchPath :: MonadIO m => m [FilePath]
+getSearchPath = liftIO System.FilePath.getSearchPath
diff --git a/src/RIO/HashMap.hs b/src/RIO/HashMap.hs
--- a/src/RIO/HashMap.hs
+++ b/src/RIO/HashMap.hs
@@ -1,8 +1,66 @@
 -- | Strict @Map@ with hashed keys. Import as:
 --
--- > import qualified RIO.HashMap as M.Hash
+-- > import qualified RIO.HashMap as HM
 module RIO.HashMap
-  ( module Data.HashMap.Strict
+  (
+    Data.HashMap.Strict.HashMap
+
+    -- * Construction
+  , Data.HashMap.Strict.empty
+  , Data.HashMap.Strict.singleton
+
+    -- * Basic interface
+  , Data.HashMap.Strict.null
+  , Data.HashMap.Strict.size
+  , Data.HashMap.Strict.member
+  , Data.HashMap.Strict.lookup
+  , Data.HashMap.Strict.lookupDefault
+  , Data.HashMap.Strict.insert
+  , Data.HashMap.Strict.insertWith
+  , Data.HashMap.Strict.delete
+  , Data.HashMap.Strict.adjust
+  , Data.HashMap.Strict.update
+  , Data.HashMap.Strict.alter
+
+    -- * Combine
+    -- ** Union
+  , Data.HashMap.Strict.union
+  , Data.HashMap.Strict.unionWith
+  , Data.HashMap.Strict.unionWithKey
+  , Data.HashMap.Strict.unions
+
+    -- * Transformations
+  , Data.HashMap.Strict.map
+  , Data.HashMap.Strict.mapWithKey
+  , Data.HashMap.Strict.traverseWithKey
+
+    -- * Difference and intersection
+  , Data.HashMap.Strict.difference
+  , Data.HashMap.Strict.differenceWith
+  , Data.HashMap.Strict.intersection
+  , Data.HashMap.Strict.intersectionWith
+  , Data.HashMap.Strict.intersectionWithKey
+
+    -- * Folds
+  , Data.HashMap.Strict.foldl'
+  , Data.HashMap.Strict.foldlWithKey'
+  , Data.HashMap.Strict.foldr
+  , Data.HashMap.Strict.foldrWithKey
+
+    -- * Filter
+  , Data.HashMap.Strict.filter
+  , Data.HashMap.Strict.filterWithKey
+  , Data.HashMap.Strict.mapMaybe
+  , Data.HashMap.Strict.mapMaybeWithKey
+
+    -- * Conversions
+  , Data.HashMap.Strict.keys
+  , Data.HashMap.Strict.elems
+
+    -- ** Lists
+  , Data.HashMap.Strict.toList
+  , Data.HashMap.Strict.fromList
+  , Data.HashMap.Strict.fromListWith
   ) where
 
 import Data.HashMap.Strict
diff --git a/src/RIO/HashMap/Partial.hs b/src/RIO/HashMap/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/HashMap/Partial.hs
@@ -0,0 +1,7 @@
+module RIO.HashMap.Partial
+  (
+  -- * Basic interface
+    (Data.HashMap.Strict.!)
+  ) where
+
+import qualified Data.HashMap.Strict
diff --git a/src/RIO/HashSet.hs b/src/RIO/HashSet.hs
--- a/src/RIO/HashSet.hs
+++ b/src/RIO/HashSet.hs
@@ -1,8 +1,48 @@
 -- | @Set@ with hashed members. Import as:
 --
--- > import qualified RIO.HashSet as S.Hash
+-- > import qualified RIO.HashSet as HS
 module RIO.HashSet
-  ( module Data.HashSet
+  (
+    Data.HashSet.HashSet
+
+  -- * Construction
+  , Data.HashSet.empty
+  , Data.HashSet.singleton
+
+  -- * Combine
+  , Data.HashSet.union
+  , Data.HashSet.unions
+
+  -- * Basic interface
+  , Data.HashSet.null
+  , Data.HashSet.size
+  , Data.HashSet.member
+  , Data.HashSet.insert
+  , Data.HashSet.delete
+
+  -- * Transformations
+  , Data.HashSet.map
+
+    -- * Difference and intersection
+  , Data.HashSet.difference
+  , Data.HashSet.intersection
+
+  -- * Folds
+  , Data.HashSet.foldl'
+  , Data.HashSet.foldr
+
+  -- * Filter
+  , Data.HashSet.filter
+
+  -- * Conversions
+
+  -- ** Lists
+  , Data.HashSet.toList
+  , Data.HashSet.fromList
+
+  -- * HashMaps
+  , Data.HashSet.toMap
+  , Data.HashSet.fromMap
   ) where
 
-import Data.HashSet
+import qualified Data.HashSet
diff --git a/src/RIO/List.hs b/src/RIO/List.hs
--- a/src/RIO/List.hs
+++ b/src/RIO/List.hs
@@ -2,13 +2,201 @@
 --
 -- > import qualified RIO.List as L
 module RIO.List
-  ( module Data.List
+  (
+  -- * Basic functions
+    (Data.List.++)
+  , Data.List.uncons
+  , Data.List.null
+  , Data.List.length
+
+  -- * List transformations
+  , Data.List.map
+  , Data.List.reverse
+
+  , Data.List.intersperse
+  , Data.List.intercalate
+  , Data.List.transpose
+
+  , Data.List.subsequences
+  , Data.List.permutations
+
+  -- * Reducing lists (folds)
+
+  , Data.List.foldl
+  , Data.List.foldl'
+  , Data.List.foldr
+
+  -- ** Special folds
+
+  , Data.List.concat
+  , Data.List.concatMap
+  , Data.List.and
+  , Data.List.or
+  , Data.List.any
+  , Data.List.all
+  , Data.List.sum
+  , Data.List.product
+
+  -- * Building lists
+
+  -- ** Scans
+  , Data.List.scanl
+  , Data.List.scanl'
+  , Data.List.scanr
+
+  -- ** Accumulating maps
+  , Data.List.mapAccumL
+  , Data.List.mapAccumR
+
+  -- ** Infinite lists
+  , Data.List.iterate
+  , Data.List.repeat
+  , Data.List.replicate
+  , Data.List.cycle
+
+  -- ** Unfolding
+  , Data.List.unfoldr
+
+  -- * Sublists
+
+  -- ** Extracting sublists
+  , Data.List.take
+  , Data.List.drop
+  , Data.List.splitAt
+
+  , Data.List.takeWhile
+  , Data.List.dropWhile
+  , Data.List.dropWhileEnd
+  , Data.List.span
+  , Data.List.break
+
+  , Data.List.stripPrefix
   , stripSuffix
   , dropPrefix
   , dropSuffix
+
+  , Data.List.group
+
+  , Data.List.inits
+  , Data.List.tails
+
+  -- ** Predicates
+  , Data.List.isPrefixOf
+  , Data.List.isSuffixOf
+  , Data.List.isInfixOf
+  , Data.List.isSubsequenceOf
+
+  -- * Searching lists
+
+  -- ** Searching by equality
+  , Data.List.elem
+  , Data.List.notElem
+  , Data.List.lookup
+
+  -- ** Searching with a predicate
+  , Data.List.find
+  , Data.List.filter
+  , Data.List.partition
+
+  -- * Indexing lists
+  -- | These functions treat a list @xs@ as a indexed collection,
+  -- with indices ranging from 0 to @'length' xs - 1@.
+
+  , Data.List.elemIndex
+  , Data.List.elemIndices
+
+  , Data.List.findIndex
+  , Data.List.findIndices
+
+  -- * Zipping and unzipping lists
+
+  , Data.List.zip
+  , Data.List.zip3
+  , Data.List.zip4
+  , Data.List.zip5
+  , Data.List.zip6
+  , Data.List.zip7
+
+  , Data.List.zipWith
+  , Data.List.zipWith3
+  , Data.List.zipWith4
+  , Data.List.zipWith5
+  , Data.List.zipWith6
+  , Data.List.zipWith7
+
+  , Data.List.unzip
+  , Data.List.unzip3
+  , Data.List.unzip4
+  , Data.List.unzip5
+  , Data.List.unzip6
+  , Data.List.unzip7
+
+  -- * Special lists
+
+  -- ** Functions on strings
+  , Data.List.lines
+  , linesCR
+  , Data.List.words
+  , Data.List.unlines
+  , Data.List.unwords
+
+  -- ** \"Set\" operations
+
+  , Data.List.nub
+
+  , Data.List.delete
+  , (Data.List.\\)
+
+  , Data.List.union
+  , Data.List.intersect
+
+  -- ** Ordered lists
+  , Data.List.sort
+  , Data.List.sortOn
+  , Data.List.insert
+
+  -- * Generalized functions
+
+  -- ** The \"@By@\" operations
+  -- | By convention, overloaded functions have a non-overloaded
+  -- counterpart whose name is suffixed with \`@By@\'.
+  --
+  -- It is often convenient to use these functions together with
+  -- 'Data.Function.on', for instance @'sortBy' ('compare'
+  -- \`on\` 'fst')@.
+
+  -- *** User-supplied equality (replacing an @Eq@ context)
+  -- | The predicate is assumed to define an equivalence.
+  , Data.List.nubBy
+  , Data.List.deleteBy
+  , Data.List.deleteFirstsBy
+  , Data.List.unionBy
+  , Data.List.intersectBy
+  , Data.List.groupBy
+
+  -- *** User-supplied comparison (replacing an @Ord@ context)
+  -- | The function is assumed to define a total ordering.
+  , Data.List.sortBy
+  , Data.List.insertBy
+  , Data.List.maximumBy
+  , Data.List.minimumBy
+
+  -- ** The \"@generic@\" operations
+  -- | The prefix \`@generic@\' indicates an overloaded function that
+  -- is a generalized version of a "Prelude" function.
+
+  , Data.List.genericLength
+  , Data.List.genericTake
+  , Data.List.genericDrop
+  , Data.List.genericSplitAt
+  , Data.List.genericIndex
+  , Data.List.genericReplicate
+
   ) where
 
-import Data.List
+import qualified Data.List
+
+import Data.List(stripPrefix)
 import Data.Maybe (fromMaybe)
 
 -- | Remove the suffix from the given list, if present
@@ -38,3 +226,12 @@
            -> [a]
            -> [a]
 dropSuffix suffix t = fromMaybe t (stripSuffix suffix t)
+
+-- | 'linesCR' breaks a 'String' up into a list of `String`s at newline
+-- 'Char's. It is very similar to 'lines', but it also removes any
+-- trailing @'\r'@ 'Char's. The resulting 'String' values do not contain
+-- newlines or trailing @'\r'@ characters.
+--
+-- @since 0.1.0.0
+linesCR :: String -> [String]
+linesCR = map (dropSuffix "\r") . lines
diff --git a/src/RIO/List/Partial.hs b/src/RIO/List/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/List/Partial.hs
@@ -0,0 +1,29 @@
+module RIO.List.Partial
+  (
+  -- * Basic functions
+    Data.List.head
+  , Data.List.last
+  , Data.List.tail
+  , Data.List.init
+
+  -- * Reducing lists (folds)
+  , Data.List.foldl1
+  , Data.List.foldl1'
+  , Data.List.foldr1
+
+  -- ** Special folds
+  , Data.List.maximum
+  , Data.List.minimum
+
+  -- * Building lists
+
+  -- ** Scans
+  , Data.List.scanl1
+  , Data.List.scanr1
+
+  -- * Indexing lists
+  , (Data.List.!!)
+  ) where
+
+import qualified Data.List
+
diff --git a/src/RIO/Map.hs b/src/RIO/Map.hs
--- a/src/RIO/Map.hs
+++ b/src/RIO/Map.hs
@@ -1,8 +1,179 @@
+{-# LANGUAGE CPP #-}
 -- | Strict @Map@. Import as:
 --
--- > import qualified RIO.Map as M
+-- > import qualified RIO.Map as Map
 module RIO.Map
-  ( module Data.Map.Strict
+  (
+  -- * Map type
+    Data.Map.Strict.Map
+
+  -- * Operators
+#if MIN_VERSION_containers(0,5,9)
+  , (Data.Map.Strict.!?)
+#endif
+  , (Data.Map.Strict.\\)
+
+  -- * Query
+  , Data.Map.Strict.null
+  , Data.Map.Strict.size
+  , Data.Map.Strict.member
+  , Data.Map.Strict.notMember
+  , Data.Map.Strict.lookup
+  , Data.Map.Strict.findWithDefault
+  , Data.Map.Strict.lookupLT
+  , Data.Map.Strict.lookupGT
+  , Data.Map.Strict.lookupLE
+  , Data.Map.Strict.lookupGE
+
+  -- * Construction
+  , Data.Map.Strict.empty
+  , Data.Map.Strict.singleton
+
+  -- ** Insertion
+  , Data.Map.Strict.insert
+  , Data.Map.Strict.insertWith
+  , Data.Map.Strict.insertWithKey
+  , Data.Map.Strict.insertLookupWithKey
+
+  -- ** Delete\/Update
+  , Data.Map.Strict.delete
+  , Data.Map.Strict.adjust
+  , Data.Map.Strict.adjustWithKey
+  , Data.Map.Strict.update
+  , Data.Map.Strict.updateWithKey
+  , Data.Map.Strict.updateLookupWithKey
+  , Data.Map.Strict.alter
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.alterF
+#endif
+
+  -- * Combine
+
+  -- ** Union
+  , Data.Map.Strict.union
+  , Data.Map.Strict.unionWith
+  , Data.Map.Strict.unionWithKey
+  , Data.Map.Strict.unions
+  , Data.Map.Strict.unionsWith
+
+  -- ** Difference
+  , Data.Map.Strict.difference
+  , Data.Map.Strict.differenceWith
+  , Data.Map.Strict.differenceWithKey
+
+  -- ** Intersection
+  , Data.Map.Strict.intersection
+  , Data.Map.Strict.intersectionWith
+  , Data.Map.Strict.intersectionWithKey
+
+  -- ** General combining functions
+  -- | See "Data.Map.Merge.Strict"
+
+  -- ** Deprecated general combining function
+
+  , Data.Map.Strict.mergeWithKey
+
+  -- * Traversal
+  -- ** Map
+  , Data.Map.Strict.map
+  , Data.Map.Strict.mapWithKey
+  , Data.Map.Strict.traverseWithKey
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.traverseMaybeWithKey
+#endif
+  , Data.Map.Strict.mapAccum
+  , Data.Map.Strict.mapAccumWithKey
+  , Data.Map.Strict.mapAccumRWithKey
+  , Data.Map.Strict.mapKeys
+  , Data.Map.Strict.mapKeysWith
+
+  -- * Folds
+  , Data.Map.Strict.foldr
+  , Data.Map.Strict.foldl
+  , Data.Map.Strict.foldrWithKey
+  , Data.Map.Strict.foldlWithKey
+  , Data.Map.Strict.foldMapWithKey
+
+  -- ** Strict folds
+  , Data.Map.Strict.foldr'
+  , Data.Map.Strict.foldl'
+  , Data.Map.Strict.foldrWithKey'
+  , Data.Map.Strict.foldlWithKey'
+
+  -- * Conversion
+  , Data.Map.Strict.elems
+  , Data.Map.Strict.keys
+  , Data.Map.Strict.assocs
+  , Data.Map.Strict.keysSet
+  , Data.Map.Strict.fromSet
+
+  -- ** Lists
+  , Data.Map.Strict.toList
+  , Data.Map.Strict.fromList
+  , Data.Map.Strict.fromListWith
+  , Data.Map.Strict.fromListWithKey
+
+  -- * Filter
+  , Data.Map.Strict.filter
+  , Data.Map.Strict.filterWithKey
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.restrictKeys
+  , Data.Map.Strict.withoutKeys
+#endif
+  , Data.Map.Strict.partition
+  , Data.Map.Strict.partitionWithKey
+
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.takeWhileAntitone
+  , Data.Map.Strict.dropWhileAntitone
+  , Data.Map.Strict.spanAntitone
+#endif
+
+  , Data.Map.Strict.mapMaybe
+  , Data.Map.Strict.mapMaybeWithKey
+  , Data.Map.Strict.mapEither
+  , Data.Map.Strict.mapEitherWithKey
+
+  , Data.Map.Strict.split
+  , Data.Map.Strict.splitLookup
+  , Data.Map.Strict.splitRoot
+
+  -- * Submap
+  , Data.Map.Strict.isSubmapOf
+  , Data.Map.Strict.isSubmapOfBy
+  , Data.Map.Strict.isProperSubmapOf
+  , Data.Map.Strict.isProperSubmapOfBy
+
+  -- * Indexed
+  , Data.Map.Strict.lookupIndex
+  , Data.Map.Strict.elemAt
+  , Data.Map.Strict.deleteAt
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.take
+  , Data.Map.Strict.drop
+  , Data.Map.Strict.splitAt
+#endif
+
+  -- * Min\/Max
+#if MIN_VERSION_containers(0,5,9)
+  , Data.Map.Strict.lookupMin
+  , Data.Map.Strict.lookupMax
+#endif
+  , Data.Map.Strict.deleteMin
+  , Data.Map.Strict.deleteMax
+  , Data.Map.Strict.updateMin
+  , Data.Map.Strict.updateMax
+  , Data.Map.Strict.updateMinWithKey
+  , Data.Map.Strict.updateMaxWithKey
+  , Data.Map.Strict.minView
+  , Data.Map.Strict.maxView
+  , Data.Map.Strict.minViewWithKey
+  , Data.Map.Strict.maxViewWithKey
+
+  -- * Debugging
+  , Data.Map.Strict.showTree
+  , Data.Map.Strict.showTreeWith
+  , Data.Map.Strict.valid
   ) where
 
-import Data.Map.Strict
+import qualified Data.Map.Strict
diff --git a/src/RIO/Map/Partial.hs b/src/RIO/Map/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Map/Partial.hs
@@ -0,0 +1,18 @@
+module RIO.Map.Partial
+  (
+  -- * Operators
+    (Data.Map.Strict.!)
+  -- * Indexed
+  , Data.Map.Strict.elemAt
+  , Data.Map.Strict.deleteAt
+  , Data.Map.Strict.findIndex
+  , Data.Map.Strict.updateAt
+
+  -- * Min\/Max
+  , Data.Map.Strict.findMin
+  , Data.Map.Strict.findMax
+  , Data.Map.Strict.deleteFindMin
+  , Data.Map.Strict.deleteFindMax
+  ) where
+
+import qualified Data.Map.Strict
diff --git a/src/RIO/Map/Unchecked.hs b/src/RIO/Map/Unchecked.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Map/Unchecked.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE CPP #-}
+-- | This module contains functions from "Data.Map.strict" that have unchecked
+--   preconditions on their input.  If these preconditions are not satisfied,
+--   the data structure may end up in an invalid state and other operations
+--   may misbehave.
+
+module RIO.Map.Unchecked
+  (
+  -- * Traversal
+  -- ** Map
+    Data.Map.Strict.mapKeysMonotonic
+
+  -- * Conversion
+  -- ** Ordered lists
+  , Data.Map.Strict.toAscList
+  , Data.Map.Strict.fromAscList
+  , Data.Map.Strict.fromAscListWith
+  , Data.Map.Strict.fromAscListWithKey
+  , Data.Map.Strict.fromDistinctAscList
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Map.Strict.toDescList
+  , Data.Map.Strict.fromDescList
+  , Data.Map.Strict.fromDescListWith
+  , Data.Map.Strict.fromDescListWithKey
+  , Data.Map.Strict.fromDistinctDescList
+#endif
+
+  ) where
+
+import qualified Data.Map.Strict
diff --git a/src/RIO/Prelude/Display.hs b/src/RIO/Prelude/Display.hs
--- a/src/RIO/Prelude/Display.hs
+++ b/src/RIO/Prelude/Display.hs
@@ -1,11 +1,12 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 module RIO.Prelude.Display
-  ( DisplayBuilder (..)
+  ( Utf8Builder (..)
   , Display (..)
   , displayShow
-  , displayBuilderToText
+  , utf8BuilderToText
+  , utf8BuilderToLazyText
   , displayBytesUtf8
-  , writeFileDisplayBuilder
+  , writeFileUtf8Builder
   ) where
 
 import Data.String (IsString (..))
@@ -16,35 +17,132 @@
 import           Data.Semigroup           (Semigroup)
 import           Data.Text                (Text)
 import qualified Data.Text.Lazy           as TL
+import qualified Data.Text.Lazy.Encoding  as TL
 import UnliftIO
 import           Data.Text.Encoding       (decodeUtf8With, encodeUtf8Builder)
 import           Data.Text.Encoding.Error (lenientDecode)
+import           Data.Int
+import           Data.Word
+import           System.Process.Typed     (ProcessConfig, setEnvInherit)
 
-newtype DisplayBuilder = DisplayBuilder { getUtf8Builder :: Builder }
+-- | A builder of binary data, with the invariant that the underlying
+-- data is supposed to be UTF-8 encoded.
+--
+-- @since 0.1.0.0
+newtype Utf8Builder = Utf8Builder { getUtf8Builder :: Builder }
   deriving (Semigroup, Monoid)
 
-instance IsString DisplayBuilder where
-  fromString = DisplayBuilder . BB.stringUtf8
+-- | @since 0.1.0.0
+instance IsString Utf8Builder where
+  fromString = Utf8Builder . BB.stringUtf8
 
+-- | A typeclass for values which can be converted to a
+-- 'Utf8Builder'. The intention of this typeclass is to provide a
+-- human-friendly display of the data.
+--
+-- @since 0.1.0.0
 class Display a where
-  display :: a -> DisplayBuilder
+  display :: a -> Utf8Builder
+
+-- | @since 0.1.0.0
+instance Display Utf8Builder where
+  display = id
+-- | @since 0.1.0.0
 instance Display Text where
-  display = DisplayBuilder . encodeUtf8Builder
+  display = Utf8Builder . encodeUtf8Builder
+-- | @since 0.1.0.0
 instance Display TL.Text where
   display = foldMap display . TL.toChunks
+-- | @since 0.1.0.0
+instance Display Char where
+  display = Utf8Builder . BB.charUtf8
+
+-- | @since 0.1.0.0
+instance Display Integer where
+  display = Utf8Builder . BB.integerDec
+-- | @since 0.1.0.0
+instance Display Float where
+  display = Utf8Builder . BB.floatDec
+instance Display Double where
+  display = Utf8Builder . BB.doubleDec
+
+-- | @since 0.1.0.0
 instance Display Int where
-  display = DisplayBuilder . BB.intDec
+  display = Utf8Builder . BB.intDec
+-- | @since 0.1.0.0
+instance Display Int8 where
+  display = Utf8Builder . BB.int8Dec
+-- | @since 0.1.0.0
+instance Display Int16 where
+  display = Utf8Builder . BB.int16Dec
+-- | @since 0.1.0.0
+instance Display Int32 where
+  display = Utf8Builder . BB.int32Dec
+-- | @since 0.1.0.0
+instance Display Int64 where
+  display = Utf8Builder . BB.int64Dec
 
-displayShow :: Show a => a -> DisplayBuilder
+-- | @since 0.1.0.0
+instance Display Word where
+  display = Utf8Builder . BB.wordDec
+-- | @since 0.1.0.0
+instance Display Word8 where
+  display = Utf8Builder . BB.word8Dec
+-- | @since 0.1.0.0
+instance Display Word16 where
+  display = Utf8Builder . BB.word16Dec
+-- | @since 0.1.0.0
+instance Display Word32 where
+  display = Utf8Builder . BB.word32Dec
+-- | @since 0.1.0.0
+instance Display Word64 where
+  display = Utf8Builder . BB.word64Dec
+
+-- | @since 0.1.0.0
+instance Display SomeException where
+  display = fromString . displayException
+-- | @since 0.1.0.0
+instance Display IOException where
+  display = fromString . displayException
+
+-- | @since 0.1.0.0
+instance Display (ProcessConfig a b c) where
+  display = displayShow . setEnvInherit
+
+-- | Use the 'Show' instance for a value to convert it to a
+-- 'Utf8Builder'.
+--
+-- @since 0.1.0.0
+displayShow :: Show a => a -> Utf8Builder
 displayShow = fromString . show
 
-displayBytesUtf8 :: ByteString -> DisplayBuilder
-displayBytesUtf8 = DisplayBuilder . BB.byteString
+-- | Convert a 'ByteString' into a 'Utf8Builder'.
+--
+-- /NOTE/ This function performs no checks to ensure that the data is,
+-- in fact, UTF8 encoded. If you provide non-UTF8 data, later
+-- functions may fail.
+--
+-- @since 0.1.0.0
+displayBytesUtf8 :: ByteString -> Utf8Builder
+displayBytesUtf8 = Utf8Builder . BB.byteString
 
-displayBuilderToText :: DisplayBuilder -> Text
-displayBuilderToText =
+-- | Convert a 'Utf8Builder' value into a strict 'Text'.
+--
+-- @since 0.1.0.0
+utf8BuilderToText :: Utf8Builder -> Text
+utf8BuilderToText =
   decodeUtf8With lenientDecode . BL.toStrict . BB.toLazyByteString . getUtf8Builder
 
-writeFileDisplayBuilder :: MonadIO m => FilePath -> DisplayBuilder -> m ()
-writeFileDisplayBuilder fp (DisplayBuilder builder) =
+-- | Convert a 'Utf8Builder' value into a lazy 'Text'.
+--
+-- @since 0.1.0.0
+utf8BuilderToLazyText :: Utf8Builder -> TL.Text
+utf8BuilderToLazyText =
+  TL.decodeUtf8With lenientDecode . BB.toLazyByteString . getUtf8Builder
+
+-- | Write the given 'Utf8Builder' value to a file.
+--
+-- @since 0.1.0.0
+writeFileUtf8Builder :: MonadIO m => FilePath -> Utf8Builder -> m ()
+writeFileUtf8Builder fp (Utf8Builder builder) =
   liftIO $ withBinaryFile fp WriteMode $ \h -> BB.hPutBuilder h builder
diff --git a/src/RIO/Prelude/Extra.hs b/src/RIO/Prelude/Extra.hs
--- a/src/RIO/Prelude/Extra.hs
+++ b/src/RIO/Prelude/Extra.hs
@@ -7,16 +7,20 @@
   , forMaybeA
   , forMaybeM
   , nubOrd
+  , whenM
+  , unlessM
   ) where
 
 import qualified Data.Set as Set
 import Data.Monoid (First (..))
 import RIO.Prelude.Reexports
 
+-- | Apply a function to a 'Left' constructor
 mapLeft :: (a1 -> a2) -> Either a1 b -> Either a2 b
 mapLeft f (Left a1) = Left (f a1)
 mapLeft _ (Right b) = Right b
 
+-- | Get a 'First' value with a default fallback
 fromFirst :: a -> First a -> a
 fromFirst x = fromMaybe x . getFirst
 
@@ -36,6 +40,7 @@
 forMaybeM :: Monad m => [a] -> (a -> m (Maybe b)) -> m [b]
 forMaybeM = flip mapMaybeM
 
+-- | Strip out duplicates
 nubOrd :: Ord a => [a] -> [a]
 nubOrd =
   loop mempty
@@ -44,3 +49,15 @@
     loop !s (a:as)
       | a `Set.member` s = loop s as
       | otherwise = a : loop (Set.insert a s) as
+
+-- | Run the second value if the first value returns 'True'
+whenM :: Monad m => m Bool -> m () -> m ()
+whenM boolM action = do
+  x <- boolM
+  if x then action else return ()
+
+-- | Run the second value if the first value returns 'False'
+unlessM :: Monad m => m Bool -> m () -> m ()
+unlessM boolM action = do
+  x <- boolM
+  if x then return () else action
diff --git a/src/RIO/Prelude/IO.hs b/src/RIO/Prelude/IO.hs
--- a/src/RIO/Prelude/IO.hs
+++ b/src/RIO/Prelude/IO.hs
@@ -2,7 +2,6 @@
   ( withLazyFile
   , readFileBinary
   , writeFileBinary
-  , ReadFileUtf8Exception (..)
   , readFileUtf8
   , writeFileUtf8
   , hPutBuilder
@@ -12,6 +11,8 @@
 import qualified Data.ByteString.Builder  as BB
 import qualified Data.ByteString          as B
 import qualified Data.ByteString.Lazy     as BL
+import qualified Data.Text.IO             as T
+import           System.IO                (hSetEncoding, utf8)
 
 -- | Lazily get the contents of a file. Unlike 'BL.readFile', this
 -- ensures that if an exception is thrown, the file handle is closed
@@ -19,13 +20,13 @@
 withLazyFile :: MonadUnliftIO m => FilePath -> (BL.ByteString -> m a) -> m a
 withLazyFile fp inner = withBinaryFile fp ReadMode $ inner <=< liftIO . BL.hGetContents
 
-data ReadFileUtf8Exception = ReadFileUtf8Exception !FilePath !UnicodeException
-  deriving (Show, Typeable)
-instance Exception ReadFileUtf8Exception
-
 -- | Write a file in UTF8 encoding
+--
+-- This function will use OS-specific line ending handling.
 writeFileUtf8 :: MonadIO m => FilePath -> Text -> m ()
-writeFileUtf8 fp = writeFileBinary fp . encodeUtf8
+writeFileUtf8 fp text = liftIO $ withFile fp WriteMode $ \h -> do
+  hSetEncoding h utf8
+  T.hPutStr h text
 
 hPutBuilder :: MonadIO m => Handle -> Builder -> m ()
 hPutBuilder h = liftIO . BB.hPutBuilder h
@@ -41,9 +42,9 @@
 
 -- | Read a file in UTF8 encoding, throwing an exception on invalid character
 -- encoding.
+--
+-- This function will use OS-specific line ending handling.
 readFileUtf8 :: MonadIO m => FilePath -> m Text
-readFileUtf8 fp = do
-  bs <- readFileBinary fp
-  case decodeUtf8' bs of
-    Left e     -> throwIO $ ReadFileUtf8Exception fp e
-    Right text -> return text
+readFileUtf8 fp = liftIO $ withFile fp ReadMode $ \h -> do
+  hSetEncoding h utf8
+  T.hGetContents h
diff --git a/src/RIO/Prelude/Logger.hs b/src/RIO/Prelude/Logger.hs
--- a/src/RIO/Prelude/Logger.hs
+++ b/src/RIO/Prelude/Logger.hs
@@ -40,6 +40,8 @@
   , CallStack
     -- * Convenience functions
   , displayCallStack
+    -- * Accessors
+  , logFuncUseColorL
   ) where
 
 import RIO.Prelude.Reexports hiding ((<>))
@@ -88,28 +90,32 @@
 -- including printing to standard output or no action at all.
 --
 -- @since 0.0.0.0
-newtype LogFunc = LogFunc
-  { _unLogFunc :: CallStack -> LogSource -> LogLevel -> DisplayBuilder -> IO ()
+data LogFunc = LogFunc
+  { unLogFunc :: !(CallStack -> LogSource -> LogLevel -> Utf8Builder -> IO ())
+  , lfOptions :: !(Maybe LogOptions)
   }
 
 -- | Perform both sets of actions per log entry.
 --
 -- @since 0.0.0.0
 instance Semigroup LogFunc where
-  LogFunc f <> LogFunc g = LogFunc $ \a b c d -> f a b c d *> g a b c d
+  LogFunc f o1 <> LogFunc g o2 = LogFunc
+    { unLogFunc = \a b c d -> f a b c d *> g a b c d
+    , lfOptions = o1 `mplus` o2
+    }
 
 -- | 'mempty' peforms no logging.
 --
 -- @since 0.0.0.0
 instance Monoid LogFunc where
-  mempty = LogFunc $ \_ _ _ _ -> return ()
+  mempty = mkLogFunc $ \_ _ _ _ -> return ()
   mappend = (<>)
 
 -- | Create a 'LogFunc' from the given function.
 --
 -- @since 0.0.0.0
-mkLogFunc :: (CallStack -> LogSource -> LogLevel -> DisplayBuilder -> IO ()) -> LogFunc
-mkLogFunc = LogFunc
+mkLogFunc :: (CallStack -> LogSource -> LogLevel -> Utf8Builder -> IO ()) -> LogFunc
+mkLogFunc f = LogFunc f Nothing
 
 -- | Generic, basic function for creating other logging functions.
 --
@@ -118,10 +124,10 @@
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => LogSource
   -> LogLevel
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logGeneric src level str = do
-  LogFunc logFunc <- view logFuncL
+  LogFunc logFunc _ <- view logFuncL
   liftIO $ logFunc callStack src level str
 
 -- | Log a debug level message with no source.
@@ -129,7 +135,7 @@
 -- @since 0.0.0.0
 logDebug
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
-  => DisplayBuilder
+  => Utf8Builder
   -> m ()
 logDebug = logGeneric "" LevelDebug
 
@@ -138,7 +144,7 @@
 -- @since 0.0.0.0
 logInfo
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
-  => DisplayBuilder
+  => Utf8Builder
   -> m ()
 logInfo = logGeneric "" LevelInfo
 
@@ -147,7 +153,7 @@
 -- @since 0.0.0.0
 logWarn
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
-  => DisplayBuilder
+  => Utf8Builder
   -> m ()
 logWarn = logGeneric "" LevelWarn
 
@@ -156,7 +162,7 @@
 -- @since 0.0.0.0
 logError
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
-  => DisplayBuilder
+  => Utf8Builder
   -> m ()
 logError = logGeneric "" LevelError
 
@@ -166,7 +172,7 @@
 logOther
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => Text -- ^ level
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logOther = logGeneric "" . LevelOther
 
@@ -176,7 +182,7 @@
 logDebugS
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => LogSource
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logDebugS src = logGeneric src LevelDebug
 
@@ -186,7 +192,7 @@
 logInfoS
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => LogSource
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logInfoS src = logGeneric src LevelInfo
 
@@ -196,7 +202,7 @@
 logWarnS
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => LogSource
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logWarnS src = logGeneric src LevelWarn
 
@@ -206,7 +212,7 @@
 logErrorS
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => LogSource
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logErrorS src = logGeneric src LevelError
 
@@ -218,7 +224,7 @@
   :: (MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack)
   => Text -- ^ level
   -> LogSource
-  -> DisplayBuilder
+  -> Utf8Builder
   -> m ()
 logOtherS src = logGeneric src . LevelOther
 
@@ -234,7 +240,7 @@
 -- provided by this module does.
 --
 -- @since 0.0.0.0
-logSticky :: (MonadIO m, HasCallStack, MonadReader env m, HasLogFunc env) => DisplayBuilder -> m ()
+logSticky :: (MonadIO m, HasCallStack, MonadReader env m, HasLogFunc env) => Utf8Builder -> m ()
 logSticky = logOther "sticky"
 
 -- | This will print out the given message with a newline and disable
@@ -242,7 +248,7 @@
 -- happens.
 --
 -- @since 0.0.0.0
-logStickyDone :: (MonadIO m, HasCallStack, MonadReader env m, HasLogFunc env) => DisplayBuilder -> m ()
+logStickyDone :: (MonadIO m, HasCallStack, MonadReader env m, HasLogFunc env) => Utf8Builder -> m ()
 logStickyDone = logOther "sticky-done"
 
 -- TODO It might be better at some point to have a 'runSticky' function
@@ -348,10 +354,17 @@
             (\var -> do
                 state <- takeMVar var
                 unless (B.null state) (logSend options "\n"))
-            (\var -> run $ inner $ LogFunc $ stickyImpl var options (simpleLogFunc options))
+            (\var -> run $ inner $ LogFunc
+                { unLogFunc = stickyImpl var options (simpleLogFunc options)
+                , lfOptions = Just options
+                }
+            )
     else
-      run $ inner $ LogFunc $ \cs src level str ->
-      simpleLogFunc options cs src (noSticky level) str
+      run $ inner $ LogFunc
+        { unLogFunc = \cs src level str ->
+             simpleLogFunc options cs src (noSticky level) str
+        , lfOptions = Just options
+        }
 
 -- | Replace Unicode characters with non-Unicode equivalents
 replaceUnicode :: Char -> Char
@@ -420,7 +433,7 @@
 setLogUseColor :: Bool -> LogOptions -> LogOptions
 setLogUseColor c options = options { logUseColor = c }
 
-simpleLogFunc :: LogOptions -> CallStack -> LogSource -> LogLevel -> DisplayBuilder -> IO ()
+simpleLogFunc :: LogOptions -> CallStack -> LogSource -> LogLevel -> Utf8Builder -> IO ()
 simpleLogFunc lo cs _src level msg =
     when (level >= logMinLevel lo) $ do
       timestamp <- getTimestamp
@@ -441,11 +454,11 @@
    setRed = "\ESC[31m"
    setMagenta = "\ESC[35m"
 
-   ansi :: DisplayBuilder -> DisplayBuilder
+   ansi :: Utf8Builder -> Utf8Builder
    ansi xs | logUseColor lo = xs
            | otherwise = mempty
 
-   getTimestamp :: IO DisplayBuilder
+   getTimestamp :: IO Utf8Builder
    getTimestamp
      | logVerboseFormat lo && logUseTime lo =
        do now <- getZonedTime
@@ -455,7 +468,7 @@
        formatTime' =
            take timestampLength . formatTime defaultTimeLocale "%F %T.%q"
 
-   getLevel :: DisplayBuilder
+   getLevel :: Utf8Builder
    getLevel
      | logVerboseFormat lo =
          case level of
@@ -470,18 +483,18 @@
              "] "
      | otherwise = mempty
 
-   getLoc :: DisplayBuilder
+   getLoc :: Utf8Builder
    getLoc
      | logVerboseFormat lo = ansi setBlack <> "\n@(" <> displayCallStack cs <> ")"
      | otherwise = mempty
 
--- | Convert a 'CallStack' value into a 'DisplayBuilder' indicating
+-- | Convert a 'CallStack' value into a 'Utf8Builder' indicating
 -- the first source location.
 --
 -- TODO Consider showing the entire call stack instead.
 --
 -- @since 0.0.0.0
-displayCallStack :: CallStack -> DisplayBuilder
+displayCallStack :: CallStack -> Utf8Builder
 displayCallStack cs =
      case reverse $ getCallStack cs of
        [] -> "<no call stack found>"
@@ -501,8 +514,8 @@
 
 stickyImpl
     :: MVar ByteString -> LogOptions
-    -> (CallStack -> LogSource -> LogLevel -> DisplayBuilder -> IO ())
-    -> CallStack -> LogSource -> LogLevel -> DisplayBuilder -> IO ()
+    -> (CallStack -> LogSource -> LogLevel -> Utf8Builder -> IO ())
+    -> CallStack -> LogSource -> LogLevel -> Utf8Builder -> IO ()
 stickyImpl ref lo logFunc loc src level msgOrig = modifyMVar_ ref $ \sticky -> do
   let backSpaceChar = '\8'
       repeating = mconcat . replicate (B.length sticky) . char7
@@ -528,3 +541,12 @@
           unless (B.null sticky) $ logSend lo (byteString sticky <> flush)
           return sticky
       | otherwise -> return sticky
+
+-- | Is the log func configured to use color output?
+--
+-- Intended for use by code which wants to optionally add additional color to
+-- its log messages.
+--
+-- @since 0.1.0.0
+logFuncUseColorL :: HasLogFunc env => SimpleGetter env Bool
+logFuncUseColorL = logFuncL.to (maybe False logUseColor . lfOptions)
diff --git a/src/RIO/Prelude/RIO.hs b/src/RIO/Prelude/RIO.hs
--- a/src/RIO/Prelude/RIO.hs
+++ b/src/RIO/Prelude/RIO.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
 module RIO.Prelude.RIO
   ( RIO (..)
   , runRIO
@@ -30,3 +31,7 @@
     askUnliftIO = RIO $ ReaderT $ \r ->
                   withUnliftIO $ \u ->
                   return (UnliftIO (unliftIO u . flip runReaderT r . unRIO))
+
+instance PrimMonad (RIO env) where
+    type PrimState (RIO env) = PrimState IO
+    primitive = RIO . ReaderT . const . primitive
diff --git a/src/RIO/Prelude/Reexports.hs b/src/RIO/Prelude/Reexports.hs
--- a/src/RIO/Prelude/Reexports.hs
+++ b/src/RIO/Prelude/Reexports.hs
@@ -2,7 +2,13 @@
 module RIO.Prelude.Reexports
   ( module UnliftIO
   -- List imports from UnliftIO?
+  , UnliftIO.Concurrent.ThreadId
+  , UnliftIO.Concurrent.myThreadId
+  , UnliftIO.Concurrent.isCurrentThreadBound
+  , UnliftIO.Concurrent.threadWaitRead
+  , UnliftIO.Concurrent.threadWaitWrite
   , UnliftIO.Concurrent.threadDelay
+  , yieldThread
   , Control.Applicative.Alternative
   , Control.Applicative.Applicative (..)
   , Control.Applicative.liftA
@@ -48,6 +54,7 @@
   , Control.Monad.Reader.asks
   , Control.Monad.Reader.local
   , Data.Bool.Bool(..)
+  , Data.Bool.bool
   , Data.Bool.not
   , Data.Bool.otherwise
   , (Data.Bool.&&)
@@ -142,19 +149,11 @@
   , Data.Maybe.mapMaybe
   , Data.Maybe.maybe
   , Data.Maybe.maybeToList
-  , Data.Monoid.All (..)
-  , Data.Monoid.Any (..)
-  , Data.Monoid.Endo (..)
-  , Data.Monoid.First (..)
-  , Data.Monoid.Last (..)
   , Data.Monoid.Monoid (..)
-  , Data.Monoid.Product (..)
-  , Data.Monoid.Sum (..)
-  , (Data.Monoid.<>)
   , Data.Ord.Ord(..)
   , Data.Ord.Ordering(..)
   , Data.Ord.comparing
-  , Data.Semigroup.Semigroup
+  , Data.Semigroup.Semigroup (..)
   , Data.Set.Set
   , Data.String.IsString(..)
   , Data.Text.Text
@@ -240,9 +239,9 @@
 import           Data.Functor             (Functor (..))
 import           Data.Int                 (Int)
 import           Data.Maybe               (Maybe, catMaybes, fromMaybe)
-import           Data.Monoid              (First (..), Monoid (..))
+import           Data.Monoid              (Monoid (..))
 import           Data.Ord                 (Ord)
-import           Data.Semigroup           (Semigroup)
+import           Data.Semigroup           (Semigroup (..))
 import           Data.String              (IsString (..))
 import           Data.Text                (Text)
 import           Data.Text.Encoding       (decodeUtf8', decodeUtf8With,
@@ -283,7 +282,6 @@
 import qualified Data.List
 import qualified Data.Map.Strict
 import qualified Data.Maybe
-import qualified Data.Monoid
 import qualified Data.Ord
 import qualified Data.Set
 import qualified Data.Text.Encoding.Error
@@ -297,3 +295,7 @@
 import qualified Prelude
 import qualified System.Exit
 import qualified Text.Read
+
+yieldThread :: MonadIO m => m ()
+yieldThread = UnliftIO.Concurrent.yield
+{-# INLINE yieldThread #-}
diff --git a/src/RIO/Prelude/Text.hs b/src/RIO/Prelude/Text.hs
--- a/src/RIO/Prelude/Text.hs
+++ b/src/RIO/Prelude/Text.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 module RIO.Prelude.Text
-  ( stripCR
-  , decodeUtf8Lenient
+  ( decodeUtf8Lenient
   , tshow
   ) where
 
@@ -9,10 +8,6 @@
 import Data.Text.Encoding (decodeUtf8With)
 import RIO.Prelude.Reexports
 import Data.Text.Encoding.Error (lenientDecode)
-
--- | Strip trailing carriage return from Text
-stripCR :: Text -> Text
-stripCR t = fromMaybe t (T.stripSuffix "\r" t)
 
 tshow :: Show a => a -> Text
 tshow = T.pack . show
diff --git a/src/RIO/Prelude/Trace.hs b/src/RIO/Prelude/Trace.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Prelude/Trace.hs
@@ -0,0 +1,186 @@
+module RIO.Prelude.Trace
+  ( -- * Text
+    trace
+  , traceId
+  , traceIO
+  , traceM
+  , traceEvent
+  , traceEventIO
+  , traceMarker
+  , traceMarkerIO
+  , traceStack
+    -- * Show
+  , traceShow
+  , traceShowId
+  , traceShowIO
+  , traceShowM
+  , traceShowEvent
+  , traceShowEventIO
+  , traceShowMarker
+  , traceShowMarkerIO
+  , traceShowStack
+    -- * Display
+  , traceDisplay
+  , traceDisplayId
+  , traceDisplayIO
+  , traceDisplayM
+  , traceDisplayEvent
+  , traceDisplayEventIO
+  , traceDisplayMarker
+  , traceDisplayMarkerIO
+  , traceDisplayStack
+  ) where
+
+import qualified Debug.Trace as Trace
+
+import           Control.Monad.IO.Class(MonadIO(..))
+import           RIO.Prelude.Display
+import           RIO.Text         (Text)
+import qualified RIO.Text as Text
+
+----------------------------------------------------
+-- Text
+----------------------------------------------------
+
+{-# WARNING trace "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+trace :: Text -> a -> a
+trace = Trace.trace . Text.unpack
+
+{-# WARNING traceId "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceId :: Text -> Text
+traceId str = Trace.trace (Text.unpack str) str
+
+{-# WARNING traceIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceIO :: MonadIO m => Text -> m ()
+traceIO = liftIO . Trace.traceIO . Text.unpack
+
+{-# WARNING traceM "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceM :: Applicative f => Text -> f ()
+traceM = Trace.traceM . Text.unpack
+
+{-# WARNING traceEvent "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceEvent :: Text -> a -> a
+traceEvent = Trace.traceEvent . Text.unpack
+
+{-# WARNING traceEventIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceEventIO :: MonadIO m => Text -> m ()
+traceEventIO = liftIO . Trace.traceEventIO . Text.unpack
+
+{-# WARNING traceMarker "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceMarker :: Text -> a -> a
+traceMarker = Trace.traceMarker . Text.unpack
+
+{-# WARNING traceMarkerIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceMarkerIO :: MonadIO m => Text -> m ()
+traceMarkerIO = liftIO . Trace.traceMarkerIO . Text.unpack
+
+{-# WARNING traceStack "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceStack :: Text -> a -> a
+traceStack = Trace.traceStack . Text.unpack
+
+----------------------------------------------------
+-- Show
+----------------------------------------------------
+
+{-# WARNING traceShow "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShow :: Show a => a -> b -> b
+traceShow = Trace.traceShow
+
+{-# WARNING traceShowId "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowId :: Show a => a -> a
+traceShowId = Trace.traceShowId
+
+{-# WARNING traceShowIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowIO :: (Show a, MonadIO m) => a -> m ()
+traceShowIO = liftIO . Trace.traceIO . show
+
+{-# WARNING traceShowM "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowM :: (Show a, Applicative f) => a -> f ()
+traceShowM = Trace.traceM . show
+
+{-# WARNING traceShowEvent "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowEvent :: Show a => a -> b -> b
+traceShowEvent = Trace.traceEvent . show
+
+{-# WARNING traceShowEventIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowEventIO :: (Show a, MonadIO m) => a -> m ()
+traceShowEventIO = liftIO . Trace.traceEventIO . show
+
+{-# WARNING traceShowMarker "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowMarker :: Show a => a -> b -> b
+traceShowMarker = Trace.traceMarker . show
+
+{-# WARNING traceShowMarkerIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowMarkerIO :: (Show a, MonadIO m) => a -> m ()
+traceShowMarkerIO = liftIO . Trace.traceMarkerIO . show
+
+{-# WARNING traceShowStack "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceShowStack :: Show a => a -> b -> b
+traceShowStack = Trace.traceStack . show
+
+----------------------------------------------------
+-- Display
+----------------------------------------------------
+
+{-# WARNING traceDisplay "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplay :: Display a => a -> b -> b
+traceDisplay = trace . utf8BuilderToText . display
+
+{-# WARNING traceDisplayId "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayId :: Display a => a -> a
+traceDisplayId x = traceDisplay x x
+
+{-# WARNING traceDisplayIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayIO :: (Display a, MonadIO m) => a -> m ()
+traceDisplayIO = traceIO . utf8BuilderToText . display
+
+{-# WARNING traceDisplayM "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayM :: (Display a, Applicative f) => a -> f ()
+traceDisplayM = traceM . utf8BuilderToText . display
+
+{-# WARNING traceDisplayEvent "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayEvent :: Display a => a -> b -> b
+traceDisplayEvent = traceEvent . utf8BuilderToText . display
+
+{-# WARNING traceDisplayEventIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayEventIO :: (Display a, MonadIO m) => a -> m ()
+traceDisplayEventIO = traceEventIO . utf8BuilderToText . display
+
+{-# WARNING traceDisplayMarker "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayMarker :: Display a => a -> b -> b
+traceDisplayMarker = traceMarker . utf8BuilderToText . display
+
+{-# WARNING traceDisplayMarkerIO "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayMarkerIO :: (Display a, MonadIO m) => a -> m ()
+traceDisplayMarkerIO = traceMarkerIO . utf8BuilderToText . display
+
+{-# WARNING traceDisplayStack "Trace statement left in code" #-}
+-- | @since 0.1.0.0
+traceDisplayStack :: Display a => a -> b -> b
+traceDisplayStack = traceStack . utf8BuilderToText . display
diff --git a/src/RIO/Process.hs b/src/RIO/Process.hs
--- a/src/RIO/Process.hs
+++ b/src/RIO/Process.hs
@@ -379,17 +379,16 @@
   x <- proc'
   end <- getMonotonicTime
   let diff = end - start
-  -- useAnsi <- asks getAnsiTerminal FIXME
-  let useAnsi = True
+  useColor <- view logFuncUseColorL
   logDebug
       ("Process finished in " <>
-      (if useAnsi then "\ESC[92m" else "") <> -- green
+      (if useColor then "\ESC[92m" else "") <> -- green
       timeSpecMilliSecondText diff <>
-      (if useAnsi then "\ESC[0m" else "") <> -- reset
+      (if useColor then "\ESC[0m" else "") <> -- reset
        ": " <> display cmdText)
   return x
 
-timeSpecMilliSecondText :: Double -> DisplayBuilder
+timeSpecMilliSecondText :: Double -> Utf8Builder
 timeSpecMilliSecondText d = display (round (d * 1000) :: Int) <> "ms"
 
 -- | Provide a 'ProcessConfig' based on the 'ProcessContext' in
diff --git a/src/RIO/Seq.hs b/src/RIO/Seq.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Seq.hs
@@ -0,0 +1,135 @@
+{-# LANGUAGE CPP #-}
+-- | @Seq@. Import as:
+--
+-- > import qualified RIO.Seq as Seq
+module RIO.Seq
+  (
+    Data.Sequence.Seq(..)
+
+    -- * Construction
+  , Data.Sequence.empty
+  , Data.Sequence.singleton
+  , (Data.Sequence.<|)
+  , (Data.Sequence.|>)
+  , (Data.Sequence.><)
+  , Data.Sequence.fromList
+  , Data.Sequence.fromFunction
+  , Data.Sequence.fromArray
+
+    -- ** Repetition
+  , Data.Sequence.replicate
+  , Data.Sequence.replicateA
+  , Data.Sequence.replicateM
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.cycleTaking
+#endif
+
+    -- ** Iterative construction
+  , Data.Sequence.iterateN
+  , Data.Sequence.unfoldr
+  , Data.Sequence.unfoldl
+
+    -- * Deconstruction
+    -- | Additional functions for deconstructing sequences are available via the
+    -- 'Foldable' instance of 'Seq'.
+
+    -- ** Queries
+  , Data.Sequence.null
+  , Data.Sequence.length
+    -- ** Views
+  , Data.Sequence.ViewL(..)
+  , Data.Sequence.viewl
+  , Data.Sequence.ViewR(..)
+  , Data.Sequence.viewr
+
+    -- * Scans
+  , Data.Sequence.scanl
+  , Data.Sequence.scanl1
+  , Data.Sequence.scanr
+  , Data.Sequence.scanr1
+
+    -- * Sublists
+  , Data.Sequence.tails
+  , Data.Sequence.inits
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.chunksOf
+#endif
+
+    -- ** Sequential searches
+  , Data.Sequence.takeWhileL
+  , Data.Sequence.takeWhileR
+  , Data.Sequence.dropWhileL
+  , Data.Sequence.dropWhileR
+  , Data.Sequence.spanl
+  , Data.Sequence.spanr
+  , Data.Sequence.breakl
+  , Data.Sequence.breakr
+  , Data.Sequence.partition
+  , Data.Sequence.filter
+
+    -- * Sorting
+  , Data.Sequence.sort
+  , Data.Sequence.sortBy
+  , Data.Sequence.unstableSort
+  , Data.Sequence.unstableSortBy
+
+    -- * Indexing
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.lookup
+  , (Data.Sequence.!?)
+#endif
+  , Data.Sequence.index
+  , Data.Sequence.adjust
+
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.adjust'
+#endif
+  , Data.Sequence.update
+  , Data.Sequence.take
+  , Data.Sequence.drop
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.insertAt
+  , Data.Sequence.deleteAt
+#endif
+  , Data.Sequence.splitAt
+
+    -- ** Indexing with predicates
+    -- | These functions perform sequential searches from the left or right ends
+    -- of the sequence elements.
+  , Data.Sequence.elemIndexL
+  , Data.Sequence.elemIndicesL
+  , Data.Sequence.elemIndexR
+  , Data.Sequence.elemIndicesR
+  , Data.Sequence.findIndexL
+  , Data.Sequence.findIndicesL
+  , Data.Sequence.findIndexR
+  , Data.Sequence.findIndicesR
+
+    -- * Folds
+    -- | General folds are available via the 'Foldable' instance of 'Seq'.
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.foldMapWithIndex
+#endif
+  , Data.Sequence.foldlWithIndex
+  , Data.Sequence.foldrWithIndex
+
+    -- * Transformations
+  , Data.Sequence.mapWithIndex
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.traverseWithIndex
+#endif
+  , Data.Sequence.reverse
+#if MIN_VERSION_containers(0, 5, 8)
+  , Data.Sequence.intersperse
+#endif
+
+    -- ** Zips
+  , Data.Sequence.zip
+  , Data.Sequence.zipWith
+  , Data.Sequence.zip3
+  , Data.Sequence.zipWith3
+  , Data.Sequence.zip4
+  , Data.Sequence.zipWith4
+  ) where
+
+import qualified Data.Sequence
diff --git a/src/RIO/Set.hs b/src/RIO/Set.hs
--- a/src/RIO/Set.hs
+++ b/src/RIO/Set.hs
@@ -1,8 +1,94 @@
+{-# LANGUAGE CPP #-}
 -- | @Set@. Import as:
 --
--- > import qualified RIO.Set as S
+-- > import qualified RIO.Set as Set
 module RIO.Set
-  ( module Data.Set
+  (
+  -- * Set type
+    Data.Set.Set
+
+  -- * Operators
+  , (Data.Set.\\)
+
+  -- * Query
+  , Data.Set.null
+  , Data.Set.size
+  , Data.Set.member
+  , Data.Set.notMember
+  , Data.Set.lookupLT
+  , Data.Set.lookupGT
+  , Data.Set.lookupLE
+  , Data.Set.lookupGE
+  , Data.Set.isSubsetOf
+  , Data.Set.isProperSubsetOf
+
+  -- * Construction
+  , Data.Set.empty
+  , Data.Set.singleton
+  , Data.Set.insert
+  , Data.Set.delete
+
+  -- * Combine
+  , Data.Set.union
+  , Data.Set.unions
+  , Data.Set.difference
+  , Data.Set.intersection
+
+  -- * Filter
+  , Data.Set.filter
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Set.takeWhileAntitone
+  , Data.Set.dropWhileAntitone
+  , Data.Set.spanAntitone
+#endif
+  , Data.Set.partition
+  , Data.Set.split
+  , Data.Set.splitMember
+  , Data.Set.splitRoot
+
+  -- * Indexed
+  , Data.Set.lookupIndex
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Set.take
+  , Data.Set.drop
+  , Data.Set.splitAt
+#endif
+
+  -- * Map
+  , Data.Set.map
+
+  -- * Folds
+  , Data.Set.foldr
+  , Data.Set.foldl
+  -- ** Strict folds
+  , Data.Set.foldr'
+  , Data.Set.foldl'
+
+  -- * Min\/Max
+#if MIN_VERSION_containers(0,5,9)
+  , Data.Set.lookupMin
+  , Data.Set.lookupMax
+#endif
+  , Data.Set.deleteMin
+  , Data.Set.deleteMax
+  , Data.Set.maxView
+  , Data.Set.minView
+
+  -- * Conversion
+
+  -- ** List
+  , Data.Set.elems
+  , Data.Set.toList
+  , Data.Set.fromList
+
+  -- ** Ordered list
+  , Data.Set.toAscList
+  , Data.Set.toDescList
+
+  -- * Debugging
+  , Data.Set.showTree
+  , Data.Set.showTreeWith
+  , Data.Set.valid
   ) where
 
-import Data.Set
+import qualified Data.Set
diff --git a/src/RIO/Set/Partial.hs b/src/RIO/Set/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Set/Partial.hs
@@ -0,0 +1,15 @@
+module RIO.Set.Partial
+  (
+  -- * Indexed
+    Data.Set.findIndex
+  , Data.Set.elemAt
+  , Data.Set.deleteAt
+
+  -- * Min\/Max
+  , Data.Set.findMin
+  , Data.Set.findMax
+  , Data.Set.deleteFindMin
+  , Data.Set.deleteFindMax
+  ) where
+
+import qualified Data.Set
diff --git a/src/RIO/Set/Unchecked.hs b/src/RIO/Set/Unchecked.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Set/Unchecked.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE CPP #-}
+
+-- | This module contains functions from "Data.Set" that have unchecked
+--   preconditions on their input.  If these preconditions are not satisfied,
+--   the data structure may end up in an invalid state and other operations
+--   may misbehave.
+module RIO.Set.Unchecked
+  (
+  -- * Map
+    Data.Set.mapMonotonic
+
+  -- * Ordered list
+  , Data.Set.fromAscList
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Set.fromDescList
+#endif
+  , Data.Set.fromDistinctAscList
+#if MIN_VERSION_containers(0,5,8)
+  , Data.Set.fromDistinctDescList
+#endif
+  ) where
+
+import qualified Data.Set
diff --git a/src/RIO/Text.hs b/src/RIO/Text.hs
--- a/src/RIO/Text.hs
+++ b/src/RIO/Text.hs
@@ -1,20 +1,153 @@
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE OverloadedStrings #-}
+
 -- | Strict @Text@. Import as:
 --
--- > import qualified RIO.Text as T
+-- > import qualified RIO.Text as Text
+--
+-- This module does not export any partial functions.  For those, see
+-- "RIO.Text.Partial"
 module RIO.Text
-  ( module Data.Text
-  , Data.Text.Encoding.encodeUtf8
-  , Data.Text.Encoding.decodeUtf8With
-  , Data.Text.Encoding.decodeUtf8'
-  , Data.Text.Encoding.Error.lenientDecode
-  , dropPrefix
-  , dropSuffix
-  ) where
+    (
+    -- * Types
+      Data.Text.Text
 
-import           Data.Text -- FIXME hide partials
+    -- * Creation and elimination
+    , Data.Text.pack
+    , Data.Text.unpack
+    , Data.Text.singleton
+    , Data.Text.empty
+
+    -- * Basic interface
+    , Data.Text.cons
+    , Data.Text.snoc
+    , Data.Text.append
+    , Data.Text.uncons
+    , Data.Text.null
+    , Data.Text.length
+    , Data.Text.compareLength
+
+    -- * Transformations
+    , Data.Text.map
+    , Data.Text.intercalate
+    , Data.Text.intersperse
+    , Data.Text.transpose
+    , Data.Text.reverse
+
+    -- ** Case conversion
+    , Data.Text.toCaseFold
+    , Data.Text.toLower
+    , Data.Text.toUpper
+    , Data.Text.toTitle
+
+    -- ** Justification
+    , Data.Text.justifyLeft
+    , Data.Text.justifyRight
+    , Data.Text.center
+
+    -- * Folds
+    , Data.Text.foldl
+    , Data.Text.foldl'
+    , Data.Text.foldr
+
+    -- ** Special folds
+    , Data.Text.concat
+    , Data.Text.concatMap
+    , Data.Text.any
+    , Data.Text.all
+
+    -- * Construction
+
+    -- ** Scans
+    , Data.Text.scanl
+    , Data.Text.scanl1 -- scanl1 and scanr1 are /not/ partial
+    , Data.Text.scanr
+    , Data.Text.scanr1
+
+    -- ** Accumulating maps
+    , Data.Text.mapAccumL
+    , Data.Text.mapAccumR
+
+    -- ** Generation and unfolding
+    , Data.Text.replicate
+    , Data.Text.unfoldr
+    , Data.Text.unfoldrN
+
+    -- * Substrings
+
+    -- ** Breaking strings
+    , Data.Text.take
+    , Data.Text.takeEnd
+    , Data.Text.drop
+    , Data.Text.dropEnd
+    , Data.Text.takeWhile
+    , Data.Text.takeWhileEnd
+    , Data.Text.dropWhile
+    , Data.Text.dropWhileEnd
+    , Data.Text.dropAround
+    , Data.Text.strip
+    , Data.Text.stripStart
+    , Data.Text.stripEnd
+    , Data.Text.splitAt
+    , Data.Text.break
+    , Data.Text.span
+    , Data.Text.group
+    , Data.Text.groupBy
+    , Data.Text.inits
+    , Data.Text.tails
+
+    -- ** Breaking into many substrings
+    , Data.Text.split
+    , Data.Text.chunksOf
+
+    -- ** Breaking into lines and words
+    , Data.Text.lines
+    , linesCR
+    , Data.Text.words
+    , Data.Text.unlines
+    , Data.Text.unwords
+
+    -- * Predicates
+    , Data.Text.isPrefixOf
+    , Data.Text.isSuffixOf
+    , Data.Text.isInfixOf
+
+    -- ** View patterns
+    , Data.Text.stripPrefix
+    , Data.Text.stripSuffix
+    , dropPrefix
+    , dropSuffix
+    , Data.Text.commonPrefixes
+
+    -- * Searching
+    , Data.Text.filter
+    , Data.Text.find
+    , Data.Text.partition
+
+    -- * Indexing
+    , Data.Text.index
+    , Data.Text.findIndex
+
+    -- * Zipping
+    , Data.Text.zip
+    , Data.Text.zipWith
+
+    -- * Low level operations
+    , Data.Text.copy
+    , Data.Text.unpackCString#
+
+    -- * Encoding
+    , Data.Text.Encoding.encodeUtf8
+    , Data.Text.Encoding.decodeUtf8With
+    , Data.Text.Encoding.decodeUtf8'
+    , Data.Text.Encoding.Error.lenientDecode
+    ) where
+
+import           Data.Maybe               (fromMaybe)
+import           Data.Text                (Text, stripPrefix, stripSuffix)
+import qualified Data.Text
 import qualified Data.Text.Encoding
 import qualified Data.Text.Encoding.Error
-import           Data.Maybe (fromMaybe)
 
 -- | Drop prefix if present, otherwise return original 'Text'.
 --
@@ -31,3 +164,12 @@
            -> Text
            -> Text
 dropSuffix suffix t = fromMaybe t (stripSuffix suffix t)
+
+-- | 'linesCR' breaks a 'Text' up into a list of `Text`s at newline
+-- 'Char's. It is very similar to 'Data.Text.lines', but it also removes
+-- any trailing @'\r'@ characters. The resulting 'Text' values do not
+-- contain newlines or trailing @'\r'@ characters.
+--
+-- @since 0.1.0.0
+linesCR :: Text -> [Text]
+linesCR = map (dropSuffix "\r") . Data.Text.lines
diff --git a/src/RIO/Text/Lazy.hs b/src/RIO/Text/Lazy.hs
--- a/src/RIO/Text/Lazy.hs
+++ b/src/RIO/Text/Lazy.hs
@@ -1,8 +1,139 @@
 -- | Lazy @Text@. Import as:
 --
--- > import qualified RIO.Text.Lazy as T.Lazy
+-- > import qualified RIO.Text.Lazy as TL
+--
+-- This module does not export any partial functions.  For those, see
+-- "RIO.Text.Lazy.Partial"
 module RIO.Text.Lazy
-  ( module Data.Text.Lazy
-  ) where
+    (
+    -- * Types
+      Data.Text.Lazy.Text
 
-import Data.Text.Lazy
+    -- * Creation and elimination
+    , Data.Text.Lazy.pack
+    , Data.Text.Lazy.unpack
+    , Data.Text.Lazy.singleton
+    , Data.Text.Lazy.empty
+    , Data.Text.Lazy.fromChunks
+    , Data.Text.Lazy.toChunks
+    , Data.Text.Lazy.toStrict
+    , Data.Text.Lazy.fromStrict
+    , Data.Text.Lazy.foldrChunks
+    , Data.Text.Lazy.foldlChunks
+
+    -- * Basic interface
+    , Data.Text.Lazy.cons
+    , Data.Text.Lazy.snoc
+    , Data.Text.Lazy.append
+    , Data.Text.Lazy.uncons
+    , Data.Text.Lazy.null
+    , Data.Text.Lazy.length
+    , Data.Text.Lazy.compareLength
+
+    -- * Transformations
+    , Data.Text.Lazy.map
+    , Data.Text.Lazy.intercalate
+    , Data.Text.Lazy.intersperse
+    , Data.Text.Lazy.transpose
+    , Data.Text.Lazy.reverse
+
+    -- ** Case conversion
+    , Data.Text.Lazy.toCaseFold
+    , Data.Text.Lazy.toLower
+    , Data.Text.Lazy.toUpper
+    , Data.Text.Lazy.toTitle
+
+    -- ** Justification
+    , Data.Text.Lazy.justifyLeft
+    , Data.Text.Lazy.justifyRight
+    , Data.Text.Lazy.center
+
+    -- * Folds
+    , Data.Text.Lazy.foldl
+    , Data.Text.Lazy.foldl'
+    , Data.Text.Lazy.foldr
+
+    -- ** Special folds
+    , Data.Text.Lazy.concat
+    , Data.Text.Lazy.concatMap
+    , Data.Text.Lazy.any
+    , Data.Text.Lazy.all
+
+    -- * Construction
+
+    -- ** Scans
+    , Data.Text.Lazy.scanl
+    , Data.Text.Lazy.scanl1  -- NB. scanl1 and scanr1 are not partial
+    , Data.Text.Lazy.scanr
+    , Data.Text.Lazy.scanr1
+
+    -- ** Accumulating maps
+    , Data.Text.Lazy.mapAccumL
+    , Data.Text.Lazy.mapAccumR
+
+    -- ** Generation and unfolding
+    , Data.Text.Lazy.repeat
+    , Data.Text.Lazy.replicate
+    , Data.Text.Lazy.cycle
+    , Data.Text.Lazy.iterate
+    , Data.Text.Lazy.unfoldr
+    , Data.Text.Lazy.unfoldrN
+
+    -- * Substrings
+
+    -- ** Breaking strings
+    , Data.Text.Lazy.take
+    , Data.Text.Lazy.takeEnd
+    , Data.Text.Lazy.drop
+    , Data.Text.Lazy.dropEnd
+    , Data.Text.Lazy.takeWhile
+    , Data.Text.Lazy.takeWhileEnd
+    , Data.Text.Lazy.dropWhile
+    , Data.Text.Lazy.dropWhileEnd
+    , Data.Text.Lazy.dropAround
+    , Data.Text.Lazy.strip
+    , Data.Text.Lazy.stripStart
+    , Data.Text.Lazy.stripEnd
+    , Data.Text.Lazy.splitAt
+    , Data.Text.Lazy.span
+    , Data.Text.Lazy.break
+    , Data.Text.Lazy.group
+    , Data.Text.Lazy.groupBy
+    , Data.Text.Lazy.inits
+    , Data.Text.Lazy.tails
+
+    -- ** Breaking into many substrings
+    , Data.Text.Lazy.split
+    , Data.Text.Lazy.chunksOf
+
+    -- ** Breaking into lines and words
+    , Data.Text.Lazy.lines
+    , Data.Text.Lazy.words
+    , Data.Text.Lazy.unlines
+    , Data.Text.Lazy.unwords
+
+    -- * Predicates
+    , Data.Text.Lazy.isPrefixOf
+    , Data.Text.Lazy.isSuffixOf
+    , Data.Text.Lazy.isInfixOf
+
+    -- ** View patterns
+    , Data.Text.Lazy.stripPrefix
+    , Data.Text.Lazy.stripSuffix
+    , Data.Text.Lazy.commonPrefixes
+
+    -- * Searching
+    , Data.Text.Lazy.filter
+    , Data.Text.Lazy.find
+    , Data.Text.Lazy.partition
+
+    -- * Indexing
+    , Data.Text.Lazy.index
+    , Data.Text.Lazy.count
+
+    -- * Zipping and unzipping
+    , Data.Text.Lazy.zip
+    , Data.Text.Lazy.zipWith
+    ) where
+
+import qualified Data.Text.Lazy
diff --git a/src/RIO/Text/Lazy/Partial.hs b/src/RIO/Text/Lazy/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Text/Lazy/Partial.hs
@@ -0,0 +1,36 @@
+-- | This module exports all the partial functions from "Data.Text.Lazy"
+
+module RIO.Text.Lazy.Partial
+    (
+    -- * Creation and elimination
+      Data.Text.Lazy.head
+    , Data.Text.Lazy.last
+    , Data.Text.Lazy.tail
+    , Data.Text.Lazy.init
+
+    -- * Transformations
+    , Data.Text.Lazy.replace
+
+    -- * Folds
+    , Data.Text.Lazy.foldl1
+    , Data.Text.Lazy.foldl1'
+    , Data.Text.Lazy.foldr1
+
+    -- ** Special folds
+    , Data.Text.Lazy.maximum
+    , Data.Text.Lazy.minimum
+
+    -- * Substrings
+
+    -- ** Breaking strings
+    , Data.Text.Lazy.breakOn
+    , Data.Text.Lazy.breakOnEnd
+
+    -- ** Breaking into many substrings
+    , Data.Text.Lazy.splitOn
+
+    -- * Searching
+    , Data.Text.Lazy.breakOnAll
+    ) where
+
+import qualified Data.Text.Lazy
diff --git a/src/RIO/Text/Partial.hs b/src/RIO/Text/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Text/Partial.hs
@@ -0,0 +1,39 @@
+-- | This module exports all the partial functions from "Data.Text"
+
+module RIO.Text.Partial
+    (
+    -- * Basic interface
+      Data.Text.head
+    , Data.Text.last
+    , Data.Text.tail
+    , Data.Text.init
+
+    -- * Transformations
+    , Data.Text.replace
+
+    -- * Folds
+    , Data.Text.foldl1
+    , Data.Text.foldl1'
+    , Data.Text.foldr1
+
+    -- ** Special folds
+    , Data.Text.maximum
+    , Data.Text.minimum
+
+    -- * Substrings
+
+    -- ** Breaking strings
+    , Data.Text.breakOn
+    , Data.Text.breakOnEnd
+
+    -- ** Breaking into many substrings
+    , Data.Text.splitOn
+
+    -- * Searching
+    , Data.Text.breakOnAll
+
+    -- * Indexing
+    , Data.Text.count
+    ) where
+
+import qualified Data.Text
diff --git a/src/RIO/Time.hs b/src/RIO/Time.hs
--- a/src/RIO/Time.hs
+++ b/src/RIO/Time.hs
@@ -1,5 +1,28 @@
 module RIO.Time
   ( module Data.Time
+  , getCurrentTime
+  , getTimeZone
+  , getCurrentTimeZone
+  , getZonedTime
+  , utcToLocalZonedTime
   ) where
 
-import Data.Time
+import Control.Monad.IO.Class
+import Data.Time hiding( getCurrentTime, getTimeZone, getCurrentTimeZone
+                       , getZonedTime, utcToLocalZonedTime)
+import qualified Data.Time
+
+getCurrentTime :: MonadIO m => m UTCTime
+getCurrentTime = liftIO Data.Time.getCurrentTime
+
+getTimeZone :: MonadIO m => UTCTime -> m TimeZone
+getTimeZone = liftIO . Data.Time.getTimeZone
+
+getCurrentTimeZone :: MonadIO m => m TimeZone
+getCurrentTimeZone = liftIO Data.Time.getCurrentTimeZone
+
+getZonedTime :: MonadIO m => m ZonedTime
+getZonedTime = liftIO Data.Time.getZonedTime
+
+utcToLocalZonedTime :: MonadIO m => UTCTime -> m ZonedTime
+utcToLocalZonedTime = liftIO . Data.Time.utcToLocalZonedTime
diff --git a/src/RIO/Vector.hs b/src/RIO/Vector.hs
--- a/src/RIO/Vector.hs
+++ b/src/RIO/Vector.hs
@@ -1,8 +1,255 @@
+{-# LANGUAGE CPP #-}
 -- | Generic @Vector@ interface. Import as:
 --
 -- > import qualified RIO.Vector as V
 module RIO.Vector
-  ( module Data.Vector.Generic
+  (
+  -- * Immutable vectors
+    Data.Vector.Generic.Vector
+
+  -- * Accessors
+  -- ** Length information
+  , Data.Vector.Generic.length
+  , Data.Vector.Generic.null
+
+  -- ** Indexing
+  , (Data.Vector.Generic.!?)
+
+  -- ** Extracting subvectors
+  , Data.Vector.Generic.slice
+  , Data.Vector.Generic.take
+  , Data.Vector.Generic.drop
+  , Data.Vector.Generic.splitAt
+
+  -- * Construction
+  -- ** Initialisation
+  , Data.Vector.Generic.empty
+  , Data.Vector.Generic.singleton
+  , Data.Vector.Generic.replicate
+  , Data.Vector.Generic.generate
+  , Data.Vector.Generic.iterateN
+
+  -- ** Monadic initialisation
+  , Data.Vector.Generic.replicateM
+  , Data.Vector.Generic.generateM
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.iterateNM
+#endif
+  , Data.Vector.Generic.create
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.createT
+#endif
+
+  -- ** Unfolding
+  , Data.Vector.Generic.unfoldr
+  , Data.Vector.Generic.unfoldrN
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.unfoldrM
+  , Data.Vector.Generic.unfoldrNM
+#endif
+  , Data.Vector.Generic.constructN
+  , Data.Vector.Generic.constructrN
+
+  -- ** Enumeration
+  , Data.Vector.Generic.enumFromN
+  , Data.Vector.Generic.enumFromStepN
+  , Data.Vector.Generic.enumFromTo
+  , Data.Vector.Generic.enumFromThenTo
+
+  -- ** Concatenation
+  , Data.Vector.Generic.cons
+  , Data.Vector.Generic.snoc
+  , (Data.Vector.Generic.++)
+  , Data.Vector.Generic.concat
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.concatNE
+#endif
+
+  -- ** Restricting memory usage
+  , Data.Vector.Generic.force
+
+  -- * Modifying vectors
+  -- ** Permutations
+  , Data.Vector.Generic.reverse
+
+  -- ** Safe destructive update
+  , Data.Vector.Generic.modify
+
+  -- * Elementwise operations
+  -- ** Indexing
+  , Data.Vector.Generic.indexed
+
+  -- ** Mapping
+  , Data.Vector.Generic.map
+  , Data.Vector.Generic.imap
+  , Data.Vector.Generic.concatMap
+
+  -- ** Monadic mapping
+  , Data.Vector.Generic.mapM
+  , Data.Vector.Generic.imapM
+  , Data.Vector.Generic.mapM_
+  , Data.Vector.Generic.imapM_
+  , Data.Vector.Generic.forM
+  , Data.Vector.Generic.forM_
+
+  -- ** Zipping
+  , Data.Vector.Generic.zipWith
+  , Data.Vector.Generic.zipWith3
+  , Data.Vector.Generic.zipWith4
+  , Data.Vector.Generic.zipWith5
+  , Data.Vector.Generic.zipWith6
+  , Data.Vector.Generic.izipWith
+  , Data.Vector.Generic.izipWith3
+  , Data.Vector.Generic.izipWith4
+  , Data.Vector.Generic.izipWith5
+  , Data.Vector.Generic.izipWith6
+  , Data.Vector.Generic.zip
+  , Data.Vector.Generic.zip3
+  , Data.Vector.Generic.zip4
+  , Data.Vector.Generic.zip5
+  , Data.Vector.Generic.zip6
+
+  -- ** Monadic zipping
+  , Data.Vector.Generic.zipWithM
+  , Data.Vector.Generic.izipWithM
+  , Data.Vector.Generic.zipWithM_
+  , Data.Vector.Generic.izipWithM_
+
+  -- ** Unzipping
+  , Data.Vector.Generic.unzip
+  , Data.Vector.Generic.unzip3
+  , Data.Vector.Generic.unzip4
+  , Data.Vector.Generic.unzip5
+  , Data.Vector.Generic.unzip6
+
+  -- * Working with predicates
+  -- ** Filtering
+  , Data.Vector.Generic.filter
+  , Data.Vector.Generic.ifilter
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.uniq
+  , Data.Vector.Generic.mapMaybe
+  , Data.Vector.Generic.imapMaybe
+#endif
+  , Data.Vector.Generic.filterM
+  , Data.Vector.Generic.takeWhile
+  , Data.Vector.Generic.dropWhile
+
+  -- ** Partitioning
+  , Data.Vector.Generic.partition
+  , Data.Vector.Generic.unstablePartition
+  , Data.Vector.Generic.span
+  , Data.Vector.Generic.break
+
+  -- ** Searching
+  , Data.Vector.Generic.elem
+  , Data.Vector.Generic.notElem
+  , Data.Vector.Generic.find
+  , Data.Vector.Generic.findIndex
+  , Data.Vector.Generic.findIndices
+  , Data.Vector.Generic.elemIndex
+  , Data.Vector.Generic.elemIndices
+
+  -- * Folding
+  , Data.Vector.Generic.foldl
+  , Data.Vector.Generic.foldl'
+  , Data.Vector.Generic.foldr
+  , Data.Vector.Generic.foldr'
+  , Data.Vector.Generic.ifoldl
+  , Data.Vector.Generic.ifoldl'
+  , Data.Vector.Generic.ifoldr
+  , Data.Vector.Generic.ifoldr'
+
+  -- ** Specialised folds
+  , Data.Vector.Generic.all
+  , Data.Vector.Generic.any
+  , Data.Vector.Generic.and
+  , Data.Vector.Generic.or
+  , Data.Vector.Generic.sum
+  , Data.Vector.Generic.product
+
+  -- ** Monadic folds
+  , Data.Vector.Generic.foldM
+  , Data.Vector.Generic.ifoldM
+  , Data.Vector.Generic.foldM'
+  , Data.Vector.Generic.ifoldM'
+  , Data.Vector.Generic.foldM_
+  , Data.Vector.Generic.ifoldM_
+  , Data.Vector.Generic.foldM'_
+  , Data.Vector.Generic.ifoldM'_
+
+  -- ** Monadic sequencing
+  , Data.Vector.Generic.sequence
+  , Data.Vector.Generic.sequence_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Generic.prescanl
+  , Data.Vector.Generic.prescanl'
+  , Data.Vector.Generic.postscanl
+  , Data.Vector.Generic.postscanl'
+  , Data.Vector.Generic.scanl
+  , Data.Vector.Generic.scanl'
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.iscanl
+  , Data.Vector.Generic.iscanl'
+#endif
+  , Data.Vector.Generic.prescanr
+  , Data.Vector.Generic.prescanr'
+  , Data.Vector.Generic.postscanr
+  , Data.Vector.Generic.postscanr'
+  , Data.Vector.Generic.scanr
+  , Data.Vector.Generic.scanr'
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.iscanr
+  , Data.Vector.Generic.iscanr'
+#endif
+
+  -- * Conversions
+  -- ** Lists
+  , Data.Vector.Generic.toList
+  , Data.Vector.Generic.fromList
+  , Data.Vector.Generic.fromListN
+
+  -- ** Different vector types
+  , Data.Vector.Generic.convert
+
+  -- ** Mutable vectors
+  , Data.Vector.Generic.freeze
+  , Data.Vector.Generic.thaw
+  , Data.Vector.Generic.copy
+
+  -- * Fusion support
+  -- ** Conversion to/from Bundles
+  , Data.Vector.Generic.stream
+  , Data.Vector.Generic.unstream
+  , Data.Vector.Generic.streamR
+  , Data.Vector.Generic.unstreamR
+
+  -- ** Recycling support
+  , Data.Vector.Generic.new
+  , Data.Vector.Generic.clone
+
+  -- * Utilities
+  -- ** Comparisons
+  , Data.Vector.Generic.eq
+  , Data.Vector.Generic.cmp
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.eqBy
+  , Data.Vector.Generic.cmpBy
+#endif
+
+  -- ** Show and Read
+  , Data.Vector.Generic.showsPrec
+  , Data.Vector.Generic.readPrec
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Generic.liftShowsPrec
+  , Data.Vector.Generic.liftReadsPrec
+#endif
+
+  -- ** @Data@ and @Typeable@
+  , Data.Vector.Generic.gfoldl
+  , Data.Vector.Generic.dataCast
+  , Data.Vector.Generic.mkType
   ) where
 
-import Data.Vector.Generic
+import qualified Data.Vector.Generic
diff --git a/src/RIO/Vector/Boxed.hs b/src/RIO/Vector/Boxed.hs
--- a/src/RIO/Vector/Boxed.hs
+++ b/src/RIO/Vector/Boxed.hs
@@ -1,8 +1,220 @@
+{-# LANGUAGE CPP #-}
 -- | Boxed @Vector@. Import as:
 --
--- > import qualified RIO.Vector.Boxed as V.Boxed
+-- > import qualified RIO.Vector.Boxed as VB
 module RIO.Vector.Boxed
-  ( module Data.Vector
+  (
+  -- * Boxed vectors
+    Data.Vector.Vector
+  , Data.Vector.MVector
+
+  -- * Accessors
+  -- ** Length information
+  , Data.Vector.length
+  , Data.Vector.null
+
+  -- ** Indexing
+  , (Data.Vector.!?)
+
+  -- ** Extracting subvectors
+  , Data.Vector.slice
+  , Data.Vector.take
+  , Data.Vector.drop
+  , Data.Vector.splitAt
+
+  -- * Construction
+  -- ** Initialisation
+  , Data.Vector.empty
+  , Data.Vector.singleton
+  , Data.Vector.replicate
+  , Data.Vector.generate
+  , Data.Vector.iterateN
+
+  -- ** Monadic initialisation
+  , Data.Vector.replicateM
+  , Data.Vector.generateM
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.iterateNM
+#endif
+  , Data.Vector.create
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.createT
+#endif
+
+  -- ** Unfolding
+  , Data.Vector.unfoldr
+  , Data.Vector.unfoldrN
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.unfoldrM
+  , Data.Vector.unfoldrNM
+#endif
+  , Data.Vector.constructN
+  , Data.Vector.constructrN
+
+  -- ** Enumeration
+  , Data.Vector.enumFromN
+  , Data.Vector.enumFromStepN
+  , Data.Vector.enumFromTo
+  , Data.Vector.enumFromThenTo
+
+  -- ** Concatenation
+  , Data.Vector.cons
+  , Data.Vector.snoc
+  , (Data.Vector.++)
+  , Data.Vector.concat
+
+  -- ** Restricting memory usage
+  , Data.Vector.force
+
+  -- * Modifying vectors
+  -- ** Permutations
+  , Data.Vector.reverse
+
+  -- ** Safe destructive update
+  , Data.Vector.modify
+
+  -- * Elementwise operations
+  -- ** Indexing
+  , Data.Vector.indexed
+
+  -- ** Mapping
+  , Data.Vector.map
+  , Data.Vector.imap
+  , Data.Vector.concatMap
+
+  -- ** Monadic mapping
+  , Data.Vector.mapM
+  , Data.Vector.imapM
+  , Data.Vector.mapM_
+  , Data.Vector.imapM_
+  , Data.Vector.forM
+  , Data.Vector.forM_
+
+  -- ** Zipping
+  , Data.Vector.zipWith
+  , Data.Vector.zipWith3
+  , Data.Vector.zipWith4
+  , Data.Vector.zipWith5
+  , Data.Vector.zipWith6
+  , Data.Vector.izipWith
+  , Data.Vector.izipWith3
+  , Data.Vector.izipWith4
+  , Data.Vector.izipWith5
+  , Data.Vector.izipWith6
+  , Data.Vector.zip
+  , Data.Vector.zip3
+  , Data.Vector.zip4
+  , Data.Vector.zip5
+  , Data.Vector.zip6
+
+  -- ** Monadic zipping
+  , Data.Vector.zipWithM
+  , Data.Vector.izipWithM
+  , Data.Vector.zipWithM_
+  , Data.Vector.izipWithM_
+
+  -- ** Unzipping
+  , Data.Vector.unzip
+  , Data.Vector.unzip3
+  , Data.Vector.unzip4
+  , Data.Vector.unzip5
+  , Data.Vector.unzip6
+
+  -- * Working with predicates
+  -- ** Filtering
+  , Data.Vector.filter
+  , Data.Vector.ifilter
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.uniq
+  , Data.Vector.mapMaybe
+  , Data.Vector.imapMaybe
+#endif
+  , Data.Vector.filterM
+  , Data.Vector.takeWhile
+  , Data.Vector.dropWhile
+
+  -- ** Partitioning
+  , Data.Vector.partition
+  , Data.Vector.unstablePartition
+  , Data.Vector.span
+  , Data.Vector.break
+
+  -- ** Searching
+  , Data.Vector.elem
+  , Data.Vector.notElem
+  , Data.Vector.find
+  , Data.Vector.findIndex
+  , Data.Vector.findIndices
+  , Data.Vector.elemIndex
+  , Data.Vector.elemIndices
+
+  -- * Folding
+  , Data.Vector.foldl
+  , Data.Vector.foldl'
+  , Data.Vector.foldr
+  , Data.Vector.foldr'
+  , Data.Vector.ifoldl
+  , Data.Vector.ifoldl'
+  , Data.Vector.ifoldr
+  , Data.Vector.ifoldr'
+
+  -- ** Specialised folds
+  , Data.Vector.all
+  , Data.Vector.any
+  , Data.Vector.and
+  , Data.Vector.or
+  , Data.Vector.sum
+  , Data.Vector.product
+
+  -- ** Monadic folds
+  , Data.Vector.foldM
+  , Data.Vector.ifoldM
+  , Data.Vector.foldM'
+  , Data.Vector.ifoldM'
+  , Data.Vector.foldM_
+  , Data.Vector.ifoldM_
+  , Data.Vector.foldM'_
+  , Data.Vector.ifoldM'_
+
+  -- ** Monadic sequencing
+  , Data.Vector.sequence
+  , Data.Vector.sequence_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.prescanl
+  , Data.Vector.prescanl'
+  , Data.Vector.postscanl
+  , Data.Vector.postscanl'
+  , Data.Vector.scanl
+  , Data.Vector.scanl'
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.iscanl
+  , Data.Vector.iscanl'
+#endif
+  , Data.Vector.prescanr
+  , Data.Vector.prescanr'
+  , Data.Vector.postscanr
+  , Data.Vector.postscanr'
+  , Data.Vector.scanr
+  , Data.Vector.scanr'
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.iscanr
+  , Data.Vector.iscanr'
+#endif
+
+  -- * Conversions
+  -- ** Lists
+  , Data.Vector.toList
+  , Data.Vector.fromList
+  , Data.Vector.fromListN
+
+  -- ** Different vector types
+  , Data.Vector.convert
+
+  -- ** Mutable vectors
+  , Data.Vector.freeze
+  , Data.Vector.thaw
+  , Data.Vector.copy
   ) where
 
-import Data.Vector
+import qualified Data.Vector
diff --git a/src/RIO/Vector/Boxed/Partial.hs b/src/RIO/Vector/Boxed/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Boxed/Partial.hs
@@ -0,0 +1,61 @@
+module RIO.Vector.Boxed.Partial
+  (
+  -- * Accessors
+  -- ** Indexing
+    (Data.Vector.!)
+  , Data.Vector.head
+  , Data.Vector.last
+
+  -- ** Monadic indexing
+  , Data.Vector.indexM
+  , Data.Vector.headM
+  , Data.Vector.lastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.init
+  , Data.Vector.tail
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , (Data.Vector.//)
+  , Data.Vector.update
+  , Data.Vector.update_
+
+  -- ** Accumulations
+  , Data.Vector.accum
+  , Data.Vector.accumulate
+  , Data.Vector.accumulate_
+
+  -- ** Permutations
+  , Data.Vector.backpermute
+
+  -- * Folding
+  , Data.Vector.foldl1
+  , Data.Vector.foldl1'
+  , Data.Vector.foldr1
+  , Data.Vector.foldr1'
+
+  -- ** Specialised folds
+  , Data.Vector.maximum
+  , Data.Vector.maximumBy
+  , Data.Vector.minimum
+  , Data.Vector.minimumBy
+  , Data.Vector.minIndex
+  , Data.Vector.minIndexBy
+  , Data.Vector.maxIndex
+  , Data.Vector.maxIndexBy
+
+  -- ** Monadic folds
+  , Data.Vector.fold1M
+  , Data.Vector.fold1M'
+  , Data.Vector.fold1M_
+  , Data.Vector.fold1M'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.scanl1
+  , Data.Vector.scanl1'
+  , Data.Vector.scanr1
+  , Data.Vector.scanr1'
+  ) where
+
+import qualified Data.Vector
diff --git a/src/RIO/Vector/Boxed/Unsafe.hs b/src/RIO/Vector/Boxed/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Boxed/Unsafe.hs
@@ -0,0 +1,42 @@
+module RIO.Vector.Boxed.Unsafe
+  (
+  -- * Accessors
+  -- ** Indexing
+    Data.Vector.unsafeIndex
+  , Data.Vector.unsafeHead
+  , Data.Vector.unsafeLast
+
+  -- ** Monadic indexing
+  , Data.Vector.unsafeIndexM
+  , Data.Vector.unsafeHeadM
+  , Data.Vector.unsafeLastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.unsafeSlice
+  , Data.Vector.unsafeInit
+  , Data.Vector.unsafeTail
+  , Data.Vector.unsafeTake
+  , Data.Vector.unsafeDrop
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , Data.Vector.unsafeUpd
+  , Data.Vector.unsafeUpdate
+  , Data.Vector.unsafeUpdate_
+
+  -- ** Accumulations
+  , Data.Vector.unsafeAccum
+  , Data.Vector.unsafeAccumulate
+  , Data.Vector.unsafeAccumulate_
+
+  -- ** Permutations
+  , Data.Vector.unsafeBackpermute
+
+  -- * Conversions
+  -- ** Mutable vectors
+  , Data.Vector.unsafeFreeze
+  , Data.Vector.unsafeThaw
+  , Data.Vector.unsafeCopy
+  ) where
+
+import qualified Data.Vector
diff --git a/src/RIO/Vector/Partial.hs b/src/RIO/Vector/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Partial.hs
@@ -0,0 +1,61 @@
+module RIO.Vector.Partial
+  (
+  -- * Accessors
+  -- ** Indexing
+    (Data.Vector.Generic.!)
+  , Data.Vector.Generic.head
+  , Data.Vector.Generic.last
+
+  -- ** Monadic indexing
+  , Data.Vector.Generic.indexM
+  , Data.Vector.Generic.headM
+  , Data.Vector.Generic.lastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Generic.init
+  , Data.Vector.Generic.tail
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , (Data.Vector.Generic.//)
+  , Data.Vector.Generic.update
+  , Data.Vector.Generic.update_
+
+  -- ** Accumulations
+  , Data.Vector.Generic.accum
+  , Data.Vector.Generic.accumulate
+  , Data.Vector.Generic.accumulate_
+
+  -- ** Permutations
+  , Data.Vector.Generic.backpermute
+
+  -- * Folding
+  , Data.Vector.Generic.foldl1
+  , Data.Vector.Generic.foldl1'
+  , Data.Vector.Generic.foldr1
+  , Data.Vector.Generic.foldr1'
+
+  -- ** Specialised folds
+  , Data.Vector.Generic.maximum
+  , Data.Vector.Generic.maximumBy
+  , Data.Vector.Generic.minimum
+  , Data.Vector.Generic.minimumBy
+  , Data.Vector.Generic.minIndex
+  , Data.Vector.Generic.minIndexBy
+  , Data.Vector.Generic.maxIndex
+  , Data.Vector.Generic.maxIndexBy
+
+  -- ** Monadic folds
+  , Data.Vector.Generic.fold1M
+  , Data.Vector.Generic.fold1M'
+  , Data.Vector.Generic.fold1M_
+  , Data.Vector.Generic.fold1M'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Generic.scanl1
+  , Data.Vector.Generic.scanl1'
+  , Data.Vector.Generic.scanr1
+  , Data.Vector.Generic.scanr1'
+  ) where
+
+import qualified Data.Vector.Generic
diff --git a/src/RIO/Vector/Storable.hs b/src/RIO/Vector/Storable.hs
--- a/src/RIO/Vector/Storable.hs
+++ b/src/RIO/Vector/Storable.hs
@@ -1,8 +1,186 @@
+{-# LANGUAGE CPP #-}
 -- | Storable @Vector@. Import as:
 --
--- > import qualified RIO.Vector.Storable as V.Storable
+-- > import qualified RIO.Vector.Storable as VS
 module RIO.Vector.Storable
-  ( module Data.Vector.Storable
+  (
+  -- * Storable vectors
+    Data.Vector.Storable.Vector
+  , Data.Vector.Storable.MVector(..)
+  , Data.Vector.Storable.Storable
+
+  -- * Accessors
+  -- ** Length information
+  , Data.Vector.Storable.length
+  , Data.Vector.Storable.null
+
+  -- ** Indexing
+  , (Data.Vector.Storable.!?)
+
+  -- ** Extracting subvectors
+  , Data.Vector.Storable.slice
+  , Data.Vector.Storable.take
+  , Data.Vector.Storable.drop
+  , Data.Vector.Storable.splitAt
+
+  -- * Construction
+  -- ** Initialisation
+  , Data.Vector.Storable.empty
+  , Data.Vector.Storable.singleton
+  , Data.Vector.Storable.replicate
+  , Data.Vector.Storable.generate
+  , Data.Vector.Storable.iterateN
+
+  -- ** Monadic initialisation
+  , Data.Vector.Storable.replicateM
+  , Data.Vector.Storable.generateM
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Storable.iterateNM
+#endif
+  , Data.Vector.Storable.create
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Storable.createT
+#endif
+
+  -- ** Unfolding
+  , Data.Vector.Storable.unfoldr
+  , Data.Vector.Storable.unfoldrN
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Storable.unfoldrM
+  , Data.Vector.Storable.unfoldrNM
+#endif
+  , Data.Vector.Storable.constructN
+  , Data.Vector.Storable.constructrN
+
+  -- ** Enumeration
+  , Data.Vector.Storable.enumFromN
+  , Data.Vector.Storable.enumFromStepN
+  , Data.Vector.Storable.enumFromTo
+  , Data.Vector.Storable.enumFromThenTo
+
+  -- ** Concatenation
+  , Data.Vector.Storable.cons
+  , Data.Vector.Storable.snoc
+  , (Data.Vector.Storable.++)
+  , Data.Vector.Storable.concat
+
+  -- ** Restricting memory usage
+  , Data.Vector.Storable.force
+
+  -- * Modifying vectors
+  -- ** Permutations
+  , Data.Vector.Storable.reverse
+
+  -- ** Safe destructive update
+  , Data.Vector.Storable.modify
+
+  -- * Elementwise operations
+  -- ** Mapping
+  , Data.Vector.Storable.map
+  , Data.Vector.Storable.imap
+  , Data.Vector.Storable.concatMap
+
+  -- ** Monadic mapping
+  , Data.Vector.Storable.mapM
+  , Data.Vector.Storable.mapM_
+  , Data.Vector.Storable.forM
+  , Data.Vector.Storable.forM_
+
+  -- ** Zipping
+  , Data.Vector.Storable.zipWith
+  , Data.Vector.Storable.zipWith3
+  , Data.Vector.Storable.zipWith4
+  , Data.Vector.Storable.zipWith5
+  , Data.Vector.Storable.zipWith6
+  , Data.Vector.Storable.izipWith
+  , Data.Vector.Storable.izipWith3
+  , Data.Vector.Storable.izipWith4
+  , Data.Vector.Storable.izipWith5
+  , Data.Vector.Storable.izipWith6
+
+  -- ** Monadic zipping
+  , Data.Vector.Storable.zipWithM
+  , Data.Vector.Storable.zipWithM_
+
+  -- * Working with predicates
+  -- ** Filtering
+  , Data.Vector.Storable.filter
+  , Data.Vector.Storable.ifilter
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Storable.uniq
+  , Data.Vector.Storable.mapMaybe
+  , Data.Vector.Storable.imapMaybe
+#endif
+  , Data.Vector.Storable.filterM
+  , Data.Vector.Storable.takeWhile
+  , Data.Vector.Storable.dropWhile
+
+  -- ** Partitioning
+  , Data.Vector.Storable.partition
+  , Data.Vector.Storable.unstablePartition
+  , Data.Vector.Storable.span
+  , Data.Vector.Storable.break
+
+  -- ** Searching
+  , Data.Vector.Storable.elem
+  , Data.Vector.Storable.notElem
+  , Data.Vector.Storable.find
+  , Data.Vector.Storable.findIndex
+  , Data.Vector.Storable.findIndices
+  , Data.Vector.Storable.elemIndex
+  , Data.Vector.Storable.elemIndices
+
+  -- * Folding
+  , Data.Vector.Storable.foldl
+  , Data.Vector.Storable.foldl'
+  , Data.Vector.Storable.foldr
+  , Data.Vector.Storable.foldr'
+  , Data.Vector.Storable.ifoldl
+  , Data.Vector.Storable.ifoldl'
+  , Data.Vector.Storable.ifoldr
+  , Data.Vector.Storable.ifoldr'
+
+  -- ** Specialised folds
+  , Data.Vector.Storable.all
+  , Data.Vector.Storable.any
+  , Data.Vector.Storable.and
+  , Data.Vector.Storable.or
+  , Data.Vector.Storable.sum
+  , Data.Vector.Storable.product
+
+  -- ** Monadic folds
+  , Data.Vector.Storable.foldM
+  , Data.Vector.Storable.foldM'
+  , Data.Vector.Storable.foldM_
+  , Data.Vector.Storable.foldM'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Storable.prescanl
+  , Data.Vector.Storable.prescanl'
+  , Data.Vector.Storable.postscanl
+  , Data.Vector.Storable.postscanl'
+  , Data.Vector.Storable.scanl
+  , Data.Vector.Storable.scanl'
+  , Data.Vector.Storable.prescanr
+  , Data.Vector.Storable.prescanr'
+  , Data.Vector.Storable.postscanr
+  , Data.Vector.Storable.postscanr'
+  , Data.Vector.Storable.scanr
+  , Data.Vector.Storable.scanr'
+
+  -- * Conversions
+  -- ** Lists
+  , Data.Vector.Storable.toList
+  , Data.Vector.Storable.fromList
+  , Data.Vector.Storable.fromListN
+
+  -- ** Different vector types
+  , Data.Vector.Storable.convert
+
+  -- ** Mutable vectors
+  , Data.Vector.Storable.freeze
+  , Data.Vector.Storable.thaw
+  , Data.Vector.Storable.copy
   ) where
 
-import Data.Vector.Storable
+import qualified Data.Vector.Storable
diff --git a/src/RIO/Vector/Storable/Partial.hs b/src/RIO/Vector/Storable/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Storable/Partial.hs
@@ -0,0 +1,59 @@
+module RIO.Vector.Storable.Partial
+  (
+  -- * Accessors
+  -- ** Indexing
+    (Data.Vector.Storable.!)
+  , Data.Vector.Storable.head
+  , Data.Vector.Storable.last
+
+  -- ** Monadic indexing
+  , Data.Vector.Storable.indexM
+  , Data.Vector.Storable.headM
+  , Data.Vector.Storable.lastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Storable.init
+  , Data.Vector.Storable.tail
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , (Data.Vector.Storable.//)
+  , Data.Vector.Storable.update_
+
+  -- ** Accumulations
+  , Data.Vector.Storable.accum
+  , Data.Vector.Storable.accumulate_
+
+  -- ** Permutations
+  , Data.Vector.Storable.backpermute
+
+  -- * Folding
+  , Data.Vector.Storable.foldl1
+  , Data.Vector.Storable.foldl1'
+  , Data.Vector.Storable.foldr1
+  , Data.Vector.Storable.foldr1'
+
+  -- ** Specialised folds
+  , Data.Vector.Storable.maximum
+  , Data.Vector.Storable.maximumBy
+  , Data.Vector.Storable.minimum
+  , Data.Vector.Storable.minimumBy
+  , Data.Vector.Storable.minIndex
+  , Data.Vector.Storable.minIndexBy
+  , Data.Vector.Storable.maxIndex
+  , Data.Vector.Storable.maxIndexBy
+
+  -- ** Monadic folds
+  , Data.Vector.Storable.fold1M
+  , Data.Vector.Storable.fold1M'
+  , Data.Vector.Storable.fold1M_
+  , Data.Vector.Storable.fold1M'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Storable.scanl1
+  , Data.Vector.Storable.scanl1'
+  , Data.Vector.Storable.scanr1
+  , Data.Vector.Storable.scanr1'
+  ) where
+
+import qualified Data.Vector.Storable
diff --git a/src/RIO/Vector/Storable/Unsafe.hs b/src/RIO/Vector/Storable/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Storable/Unsafe.hs
@@ -0,0 +1,54 @@
+module RIO.Vector.Storable.Unsafe
+  (
+  -- * Accessors
+  -- ** Indexing
+    Data.Vector.Storable.unsafeIndex
+  , Data.Vector.Storable.unsafeHead
+  , Data.Vector.Storable.unsafeLast
+
+  -- ** Monadic indexing
+  , Data.Vector.Storable.unsafeIndexM
+  , Data.Vector.Storable.unsafeHeadM
+  , Data.Vector.Storable.unsafeLastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Storable.unsafeSlice
+  , Data.Vector.Storable.unsafeInit
+  , Data.Vector.Storable.unsafeTail
+  , Data.Vector.Storable.unsafeTake
+  , Data.Vector.Storable.unsafeDrop
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , Data.Vector.Storable.unsafeUpd
+  , Data.Vector.Storable.unsafeUpdate_
+
+  -- ** Accumulations
+  , Data.Vector.Storable.unsafeAccum
+  , Data.Vector.Storable.unsafeAccumulate_
+
+  -- ** Permutations
+  , Data.Vector.Storable.unsafeBackpermute
+
+  -- * Conversions
+  -- ** Mutable vectors
+  , Data.Vector.Storable.unsafeFreeze
+  , Data.Vector.Storable.unsafeThaw
+  , Data.Vector.Storable.unsafeCopy
+
+  -- * Raw pointers
+  , Data.Vector.Storable.unsafeFromForeignPtr
+  , Data.Vector.Storable.unsafeFromForeignPtr0
+  , Data.Vector.Storable.unsafeToForeignPtr
+  , Data.Vector.Storable.unsafeToForeignPtr0
+  , unsafeWith
+  ) where
+
+import Data.Vector.Storable(Storable, Vector)
+import qualified Data.Vector.Storable
+import Foreign.Ptr(Ptr)
+import UnliftIO
+
+-- | Lifted version of 'Data.Vector.Storable.unsafeWith'
+unsafeWith :: (MonadUnliftIO m, Storable a) => Vector a -> (Ptr a -> m b) -> m b
+unsafeWith vec action = withRunInIO $ \unlifter -> Data.Vector.Storable.unsafeWith vec (unlifter . action)
diff --git a/src/RIO/Vector/Unboxed.hs b/src/RIO/Vector/Unboxed.hs
--- a/src/RIO/Vector/Unboxed.hs
+++ b/src/RIO/Vector/Unboxed.hs
@@ -1,8 +1,209 @@
+{-# LANGUAGE CPP #-}
 -- | Unboxed @Vector@. Import as:
 --
--- > import qualified RIO.Vector.Unboxed as V.Unboxed
+-- > import qualified RIO.Vector.Unboxed as VU
 module RIO.Vector.Unboxed
-  ( module Data.Vector.Unboxed
+  (
+  -- * Unboxed vectors
+    Data.Vector.Unboxed.Vector
+  , Data.Vector.Unboxed.MVector(..)
+  , Data.Vector.Unboxed.Unbox
+
+  -- * Accessors
+  -- ** Length information
+  , Data.Vector.Unboxed.length
+  , Data.Vector.Unboxed.null
+
+  -- ** Indexing
+  , (Data.Vector.Unboxed.!?)
+
+  -- ** Extracting subvectors
+  , Data.Vector.Unboxed.slice
+  , Data.Vector.Unboxed.take
+  , Data.Vector.Unboxed.drop
+  , Data.Vector.Unboxed.splitAt
+
+  -- * Construction
+  -- ** Initialisation
+  , Data.Vector.Unboxed.empty
+  , Data.Vector.Unboxed.singleton
+  , Data.Vector.Unboxed.replicate
+  , Data.Vector.Unboxed.generate
+  , Data.Vector.Unboxed.iterateN
+
+  -- ** Monadic initialisation
+  , Data.Vector.Unboxed.replicateM
+  , Data.Vector.Unboxed.generateM
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Unboxed.iterateNM
+#endif
+  , Data.Vector.Unboxed.create
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Unboxed.createT
+#endif
+
+  -- ** Unfolding
+  , Data.Vector.Unboxed.unfoldr
+  , Data.Vector.Unboxed.unfoldrN
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Unboxed.unfoldrM
+  , Data.Vector.Unboxed.unfoldrNM
+#endif
+  , Data.Vector.Unboxed.constructN
+  , Data.Vector.Unboxed.constructrN
+
+  -- ** Enumeration
+  , Data.Vector.Unboxed.enumFromN
+  , Data.Vector.Unboxed.enumFromStepN
+  , Data.Vector.Unboxed.enumFromTo
+  , Data.Vector.Unboxed.enumFromThenTo
+
+  -- ** Concatenation
+  , Data.Vector.Unboxed.cons
+  , Data.Vector.Unboxed.snoc
+  , (Data.Vector.Unboxed.++)
+  , Data.Vector.Unboxed.concat
+
+  -- ** Restricting memory usage
+  , Data.Vector.Unboxed.force
+
+  -- * Modifying vectors
+  -- ** Permutations
+  , Data.Vector.Unboxed.reverse
+
+  -- ** Safe destructive update
+  , Data.Vector.Unboxed.modify
+
+  -- * Elementwise operations
+  -- ** Indexing
+  , Data.Vector.Unboxed.indexed
+
+  -- ** Mapping
+  , Data.Vector.Unboxed.map
+  , Data.Vector.Unboxed.imap
+  , Data.Vector.Unboxed.concatMap
+
+  -- ** Monadic mapping
+  , Data.Vector.Unboxed.mapM
+  , Data.Vector.Unboxed.imapM
+  , Data.Vector.Unboxed.mapM_
+  , Data.Vector.Unboxed.imapM_
+  , Data.Vector.Unboxed.forM
+  , Data.Vector.Unboxed.forM_
+
+  -- ** Zipping
+  , Data.Vector.Unboxed.zipWith
+  , Data.Vector.Unboxed.zipWith3
+  , Data.Vector.Unboxed.zipWith4
+  , Data.Vector.Unboxed.zipWith5
+  , Data.Vector.Unboxed.zipWith6
+  , Data.Vector.Unboxed.izipWith
+  , Data.Vector.Unboxed.izipWith3
+  , Data.Vector.Unboxed.izipWith4
+  , Data.Vector.Unboxed.izipWith5
+  , Data.Vector.Unboxed.izipWith6
+  , Data.Vector.Unboxed.zip
+  , Data.Vector.Unboxed.zip3
+  , Data.Vector.Unboxed.zip4
+  , Data.Vector.Unboxed.zip5
+  , Data.Vector.Unboxed.zip6
+
+  -- ** Monadic zipping
+  , Data.Vector.Unboxed.zipWithM
+  , Data.Vector.Unboxed.izipWithM
+  , Data.Vector.Unboxed.zipWithM_
+  , Data.Vector.Unboxed.izipWithM_
+
+  -- ** Unzipping
+  , Data.Vector.Unboxed.unzip
+  , Data.Vector.Unboxed.unzip3
+  , Data.Vector.Unboxed.unzip4
+  , Data.Vector.Unboxed.unzip5
+  , Data.Vector.Unboxed.unzip6
+
+  -- * Working with predicates
+  -- ** Filtering
+  , Data.Vector.Unboxed.filter
+  , Data.Vector.Unboxed.ifilter
+#if MIN_VERSION_vector(0,12,0)
+  , Data.Vector.Unboxed.uniq
+  , Data.Vector.Unboxed.mapMaybe
+  , Data.Vector.Unboxed.imapMaybe
+#endif
+  , Data.Vector.Unboxed.filterM
+  , Data.Vector.Unboxed.takeWhile
+  , Data.Vector.Unboxed.dropWhile
+
+  -- ** Partitioning
+  , Data.Vector.Unboxed.partition
+  , Data.Vector.Unboxed.unstablePartition
+  , Data.Vector.Unboxed.span
+  , Data.Vector.Unboxed.break
+
+  -- ** Searching
+  , Data.Vector.Unboxed.elem
+  , Data.Vector.Unboxed.notElem
+  , Data.Vector.Unboxed.find
+  , Data.Vector.Unboxed.findIndex
+  , Data.Vector.Unboxed.findIndices
+  , Data.Vector.Unboxed.elemIndex
+  , Data.Vector.Unboxed.elemIndices
+
+  -- * Folding
+  , Data.Vector.Unboxed.foldl
+  , Data.Vector.Unboxed.foldl'
+  , Data.Vector.Unboxed.foldr
+  , Data.Vector.Unboxed.foldr'
+  , Data.Vector.Unboxed.ifoldl
+  , Data.Vector.Unboxed.ifoldl'
+  , Data.Vector.Unboxed.ifoldr
+  , Data.Vector.Unboxed.ifoldr'
+
+  -- ** Specialised folds
+  , Data.Vector.Unboxed.all
+  , Data.Vector.Unboxed.any
+  , Data.Vector.Unboxed.and
+  , Data.Vector.Unboxed.or
+  , Data.Vector.Unboxed.sum
+  , Data.Vector.Unboxed.product
+
+  -- ** Monadic folds
+  , Data.Vector.Unboxed.foldM
+  , Data.Vector.Unboxed.ifoldM
+  , Data.Vector.Unboxed.foldM'
+  , Data.Vector.Unboxed.ifoldM'
+  , Data.Vector.Unboxed.foldM_
+  , Data.Vector.Unboxed.ifoldM_
+  , Data.Vector.Unboxed.foldM'_
+  , Data.Vector.Unboxed.ifoldM'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Unboxed.prescanl
+  , Data.Vector.Unboxed.prescanl'
+  , Data.Vector.Unboxed.postscanl
+  , Data.Vector.Unboxed.postscanl'
+  , Data.Vector.Unboxed.scanl
+  , Data.Vector.Unboxed.scanl'
+  , Data.Vector.Unboxed.prescanr
+  , Data.Vector.Unboxed.prescanr'
+  , Data.Vector.Unboxed.postscanr
+  , Data.Vector.Unboxed.postscanr'
+  , Data.Vector.Unboxed.scanr
+  , Data.Vector.Unboxed.scanr'
+
+  -- * Conversions
+  -- ** Lists
+  , Data.Vector.Unboxed.toList
+  , Data.Vector.Unboxed.fromList
+  , Data.Vector.Unboxed.fromListN
+
+  -- ** Different vector types
+  , Data.Vector.Unboxed.convert
+
+  -- ** Mutable vectors
+  , Data.Vector.Unboxed.freeze
+  , Data.Vector.Unboxed.thaw
+  , Data.Vector.Unboxed.copy
   ) where
 
-import Data.Vector.Unboxed
+import qualified Data.Vector.Unboxed
diff --git a/src/RIO/Vector/Unboxed/Partial.hs b/src/RIO/Vector/Unboxed/Partial.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Unboxed/Partial.hs
@@ -0,0 +1,61 @@
+module RIO.Vector.Unboxed.Partial
+  (
+  -- * Accessors
+  -- ** Indexing
+    (Data.Vector.Unboxed.!)
+  , Data.Vector.Unboxed.head
+  , Data.Vector.Unboxed.last
+
+  -- ** Monadic indexing
+  , Data.Vector.Unboxed.indexM
+  , Data.Vector.Unboxed.headM
+  , Data.Vector.Unboxed.lastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Unboxed.init
+  , Data.Vector.Unboxed.tail
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , (Data.Vector.Unboxed.//)
+  , Data.Vector.Unboxed.update
+  , Data.Vector.Unboxed.update_
+
+  -- ** Accumulations
+  , Data.Vector.Unboxed.accum
+  , Data.Vector.Unboxed.accumulate
+  , Data.Vector.Unboxed.accumulate_
+
+  -- ** Permutations
+  , Data.Vector.Unboxed.backpermute
+
+  -- * Folding
+  , Data.Vector.Unboxed.foldl1
+  , Data.Vector.Unboxed.foldl1'
+  , Data.Vector.Unboxed.foldr1
+  , Data.Vector.Unboxed.foldr1'
+
+  -- ** Specialised folds
+  , Data.Vector.Unboxed.maximum
+  , Data.Vector.Unboxed.maximumBy
+  , Data.Vector.Unboxed.minimum
+  , Data.Vector.Unboxed.minimumBy
+  , Data.Vector.Unboxed.minIndex
+  , Data.Vector.Unboxed.minIndexBy
+  , Data.Vector.Unboxed.maxIndex
+  , Data.Vector.Unboxed.maxIndexBy
+
+  -- ** Monadic folds
+  , Data.Vector.Unboxed.fold1M
+  , Data.Vector.Unboxed.fold1M'
+  , Data.Vector.Unboxed.fold1M_
+  , Data.Vector.Unboxed.fold1M'_
+
+  -- * Prefix sums (scans)
+  , Data.Vector.Unboxed.scanl1
+  , Data.Vector.Unboxed.scanl1'
+  , Data.Vector.Unboxed.scanr1
+  , Data.Vector.Unboxed.scanr1'
+  ) where
+
+import qualified Data.Vector.Unboxed
diff --git a/src/RIO/Vector/Unboxed/Unsafe.hs b/src/RIO/Vector/Unboxed/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Unboxed/Unsafe.hs
@@ -0,0 +1,42 @@
+module RIO.Vector.Unboxed.Unsafe
+  (
+  -- * Accessors
+  -- ** Indexing
+    Data.Vector.Unboxed.unsafeIndex
+  , Data.Vector.Unboxed.unsafeHead
+  , Data.Vector.Unboxed.unsafeLast
+
+  -- ** Monadic indexing
+  , Data.Vector.Unboxed.unsafeIndexM
+  , Data.Vector.Unboxed.unsafeHeadM
+  , Data.Vector.Unboxed.unsafeLastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Unboxed.unsafeSlice
+  , Data.Vector.Unboxed.unsafeInit
+  , Data.Vector.Unboxed.unsafeTail
+  , Data.Vector.Unboxed.unsafeTake
+  , Data.Vector.Unboxed.unsafeDrop
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , Data.Vector.Unboxed.unsafeUpd
+  , Data.Vector.Unboxed.unsafeUpdate
+  , Data.Vector.Unboxed.unsafeUpdate_
+
+  -- ** Accumulations
+  , Data.Vector.Unboxed.unsafeAccum
+  , Data.Vector.Unboxed.unsafeAccumulate
+  , Data.Vector.Unboxed.unsafeAccumulate_
+
+  -- ** Permutations
+  , Data.Vector.Unboxed.unsafeBackpermute
+
+  -- * Conversions
+  -- ** Mutable vectors
+  , Data.Vector.Unboxed.unsafeFreeze
+  , Data.Vector.Unboxed.unsafeThaw
+  , Data.Vector.Unboxed.unsafeCopy
+  ) where
+
+import qualified Data.Vector.Unboxed
diff --git a/src/RIO/Vector/Unsafe.hs b/src/RIO/Vector/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/RIO/Vector/Unsafe.hs
@@ -0,0 +1,45 @@
+module RIO.Vector.Unsafe
+  (
+  -- * Immutable vectors
+    Data.Vector.Generic.Vector(..)
+
+  -- * Accessors
+  -- ** Indexing
+  , Data.Vector.Generic.unsafeIndex
+  , Data.Vector.Generic.unsafeHead
+  , Data.Vector.Generic.unsafeLast
+
+  -- ** Monadic indexing
+  , Data.Vector.Generic.unsafeIndexM
+  , Data.Vector.Generic.unsafeHeadM
+  , Data.Vector.Generic.unsafeLastM
+
+  -- ** Extracting subvectors
+  , Data.Vector.Generic.unsafeSlice
+  , Data.Vector.Generic.unsafeInit
+  , Data.Vector.Generic.unsafeTail
+  , Data.Vector.Generic.unsafeTake
+  , Data.Vector.Generic.unsafeDrop
+
+  -- * Modifying vectors
+  -- ** Bulk updates
+  , Data.Vector.Generic.unsafeUpd
+  , Data.Vector.Generic.unsafeUpdate
+  , Data.Vector.Generic.unsafeUpdate_
+
+  -- ** Accumulations
+  , Data.Vector.Generic.unsafeAccum
+  , Data.Vector.Generic.unsafeAccumulate
+  , Data.Vector.Generic.unsafeAccumulate_
+
+  -- ** Permutations
+  , Data.Vector.Generic.unsafeBackpermute
+
+  -- * Conversions
+  -- ** Mutable vectors
+  , Data.Vector.Generic.unsafeFreeze
+  , Data.Vector.Generic.unsafeThaw
+  , Data.Vector.Generic.unsafeCopy
+  ) where
+
+import qualified Data.Vector.Generic
diff --git a/test/RIO/Prelude/IOSpec.hs b/test/RIO/Prelude/IOSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/RIO/Prelude/IOSpec.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ViewPatterns #-}
+module RIO.Prelude.IOSpec (spec) where
+
+import RIO
+import Test.Hspec
+import Test.Hspec.QuickCheck
+import qualified RIO.ByteString as B
+import qualified RIO.Text as T
+
+spec :: Spec
+spec = do
+  prop "binary file read/write" $ \(B.pack -> bs1) ->
+    withSystemTempFile "binary-read-write" $ \fp h -> do
+      hClose h
+      writeFileBinary fp bs1
+      bs2 <- readFileBinary fp
+      bs2 `shouldBe` bs1
+  -- filter our \r for Windows
+  prop "text file read/write" $ \(T.pack . filter (/= '\r') -> text1) ->
+    withSystemTempFile "binary-read-write" $ \fp h -> do
+      hClose h
+      writeFileUtf8 fp text1
+      text2 <- readFileUtf8 fp
+      text2 `shouldBe` text1
diff --git a/test/RIO/PreludeSpec.hs b/test/RIO/PreludeSpec.hs
--- a/test/RIO/PreludeSpec.hs
+++ b/test/RIO/PreludeSpec.hs
@@ -7,13 +7,32 @@
 
 spec :: Spec
 spec = do
-  it "sanity" $ do
-    ref <- newURef (0 :: Int)
-    x <- readURef ref
-    x `shouldBe` 0
-    writeURef ref 1
-    y <- readURef ref
-    y `shouldBe` 1
-    modifyURef ref (+ 1)
-    z <- readURef ref
-    z `shouldBe` 2
+  describe "URef" $ do
+    it "sanity" $ do
+      ref <- newURef (0 :: Int)
+      x <- readURef ref
+      x `shouldBe` 0
+      writeURef ref 1
+      y <- readURef ref
+      y `shouldBe` 1
+      modifyURef ref (+ 1)
+      z <- readURef ref
+      z `shouldBe` 2
+  describe "whenM" $ do
+    it "returns True" $ do
+      ref <- newIORef False
+      whenM (return True) (writeIORef ref True)
+      readIORef ref `shouldReturn` True
+    it "returns False" $ do
+      ref <- newIORef False
+      whenM (return False) (writeIORef ref True)
+      readIORef ref `shouldReturn` False
+  describe "unlessM" $ do
+    it "returns True" $ do
+      ref <- newIORef False
+      unlessM (return True) (writeIORef ref True)
+      readIORef ref `shouldReturn` False
+    it "returns False" $ do
+      ref <- newIORef False
+      unlessM (return False) (writeIORef ref True)
+      readIORef ref `shouldReturn` True
