diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2016 Tom Sydney Kerckhove http://cs-syd.eu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/introduction.cabal b/introduction.cabal
new file mode 100644
--- /dev/null
+++ b/introduction.cabal
@@ -0,0 +1,69 @@
+name:                introduction
+version:             0.0.1.0
+synopsis:            A prelude for safe new projects
+description:         A prelude for safe new projects
+homepage:            https://github.com/NorfairKing/introduction
+license:             MIT
+license-file:        LICENSE
+author:              Tom Sydney Kerckhove
+maintainer:          syd.kerckhove@gmail.com
+copyright:           2016 Tom Sydney Kerckhove
+category:            Prelude
+build-type:          Simple
+cabal-version:       >=1.10
+tested-with:
+  GHC == 8.0.1
+Bug-Reports:         https://github.com/NorfairKing/introduction/issues
+
+library
+  hs-source-dirs:
+    src
+
+  exposed-modules:
+    Introduction
+    Unsafe
+
+  other-modules:
+    Base
+    Bool
+    Concurrency
+    Debug
+    Either
+    Errors
+    Functor
+    IOString
+    List
+    Monad
+    FilePaths
+
+  ghc-options:
+    -Wall
+    -fwarn-implicit-prelude
+
+  build-depends:
+      base                >= 4.9      && < 5   
+    , ghc-prim            >= 0.3      && < 0.6 
+    , async               >= 2.1      && < 2.2 
+    , bytestring          >= 0.10     && < 0.11
+    , containers          >= 0.5      && < 0.6 
+    , deepseq             >= 1.3      && < 1.6 
+    , exceptions          >= 0.8      && < 0.9
+    , filepath            >= 1.4      && < 1.5
+    , lifted-base         >= 0.2      && < 0.3
+    , monad-control       >= 1.0      && < 1.1
+    , mtl                 >= 2.1      && < 2.3 
+    , path                >= 0.5      && < 0.6
+    , path-io             >= 1.2      && < 1.3
+    , safe                >= 0.3      && < 0.4 
+    , stm                 >= 2.4      && < 2.5 
+    , string-conv         >= 0.1      && < 0.2 
+    , text                >= 1.2      && < 1.3 
+    , transformers        >= 0.4      && < 0.6 
+    , transformers-base   >= 0.4      && < 0.6 
+    , validity            >= 0.3.0.4  && < 0.4
+    , validity-containers >= 0.1.0.1  && < 0.2
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/NorfairKing/introduction
diff --git a/src/Base.hs b/src/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/Base.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Unsafe #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ExplicitNamespaces #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Base
+    ( module X
+    ) where
+
+import GHC.Num as X
+import GHC.Enum as X
+import GHC.Real as X
+import GHC.Float as X
+import GHC.Show as X (
+      Show(..)
+    )
+
+import GHC.Base as X (
+      (++)
+    , seq
+    , asTypeOf
+    , ord
+    )
+
+import System.IO as X (
+      print
+    , putStr
+    , putStrLn
+    , writeFile
+    , readFile
+    , appendFile
+    )
+
+import GHC.Types as X (
+      Bool
+    , Char
+    , Int
+    , Word
+    , Ordering
+    , IO
+    , Coercible
+    )
+
+import Data.Kind as X (
+      type (*)
+    , type Type
+    )
diff --git a/src/Bool.hs b/src/Bool.hs
new file mode 100644
--- /dev/null
+++ b/src/Bool.hs
@@ -0,0 +1,41 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Safe              #-}
+
+module Bool
+    ( whenM
+    , unlessM
+    , ifM
+    , guardM
+    , bool
+    , (&&&)
+    , (|||)
+    ) where
+
+import           Control.Monad (Monad, MonadPlus, guard, unless, when, (=<<),
+                                (>>=))
+import           Data.Bool     (Bool, (&&), (||))
+import           Data.Function (flip)
+
+bool :: a -> a -> Bool -> a
+bool f t p = if p then t else f
+
+whenM :: Monad m => m Bool -> m () -> m ()
+whenM p m =
+  p >>= flip when m
+
+unlessM :: Monad m => m Bool -> m () -> m ()
+unlessM p m =
+  p >>= flip unless m
+
+ifM :: Monad m => m Bool -> m a -> m a -> m a
+ifM p x y = p >>= \b -> if b then x else y
+
+guardM :: MonadPlus m => m Bool -> m ()
+guardM f = guard =<< f
+
+
+(&&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
+f &&& g = \a -> f a && g a
+
+(|||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
+f ||| g = \a -> f a || g a
diff --git a/src/Concurrency.hs b/src/Concurrency.hs
new file mode 100644
--- /dev/null
+++ b/src/Concurrency.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Concurrency (
+    module X
+  ) where
+
+import           Control.Concurrent.Async    as X
+import           Control.Concurrent.Lifted   as X
+import           Control.Exception.Lifted    as X hiding (Handler)
+import           Control.Monad.STM           as X
+import           Control.Monad.Trans.Control as X
diff --git a/src/Debug.hs b/src/Debug.hs
new file mode 100644
--- /dev/null
+++ b/src/Debug.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Unsafe            #-}
+
+module Debug
+  ( undefined
+  , error
+  , trace
+  , traceM
+  , traceIO
+  , traceShow
+  , traceShowM
+  , notImplemented
+  ) where
+
+import           Control.Monad (Monad, return)
+import           Data.String   (String)
+
+import           Base          as P
+import qualified Debug.Trace   as T
+import qualified GHC.Err       as P (error, undefined)
+
+{-# WARNING undefined "'undefined' remains in code" #-}
+undefined :: a
+undefined = P.undefined
+
+{-# WARNING error "'error' remains in code" #-}
+error :: String -> a
+error = P.error
+
+{-# WARNING trace "'trace' remains in code" #-}
+trace :: String -> a -> a
+trace = T.trace
+
+{-# WARNING traceShow "'traceShow' remains in code" #-}
+traceShow :: P.Show a => a -> b -> b
+traceShow a b = T.trace (P.show a) b
+
+{-# WARNING traceShowM "'traceShowM' remains in code" #-}
+traceShowM :: (P.Show a, Monad m) => a -> m ()
+traceShowM a = traceM (P.show a)
+
+{-# WARNING traceM "'traceM' remains in code" #-}
+traceM :: (Monad m) => String -> m ()
+traceM s = T.trace s (return ())
+
+{-# WARNING traceIO "'traceIO' remains in code" #-}
+traceIO :: String -> P.IO ()
+traceIO = T.traceIO
+
+{-# WARNING notImplemented "'notImplemented' remains in code" #-}
+notImplemented :: a
+notImplemented = P.error "Not implemented"
diff --git a/src/Either.hs b/src/Either.hs
new file mode 100644
--- /dev/null
+++ b/src/Either.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Safe              #-}
+
+module Either
+  ( maybeToLeft
+  , maybeToRight
+  , leftToMaybe
+  , rightToMaybe
+  , maybeToEither
+  , whenIsRight
+  , whenIsLeft
+  , whenRightDo
+  , whenLeftDo
+  ) where
+
+import           Control.Applicative (Applicative (pure))
+import           Data.Either   (Either (..), either)
+import           Data.Function (const)
+import           Data.Maybe    (Maybe (..), maybe)
+import           Data.Monoid   (Monoid, mempty)
+
+leftToMaybe :: Either l r -> Maybe l
+leftToMaybe = either Just (const Nothing)
+
+rightToMaybe :: Either l r -> Maybe r
+rightToMaybe = either (const Nothing) Just
+
+maybeToRight :: l -> Maybe r -> Either l r
+maybeToRight l = maybe (Left l) Right
+
+maybeToLeft :: r -> Maybe l -> Either l r
+maybeToLeft r = maybe (Right r) Left
+
+maybeToEither :: Monoid b => (a -> b) -> Maybe a -> b
+maybeToEither = maybe mempty
+
+whenIsRight :: (Applicative m) => Either l r -> m () -> m ()
+whenIsRight (Right _) f = f
+whenIsRight (Left _)  _ = pure ()
+
+whenIsLeft :: (Applicative m) => Either l r -> m () -> m ()
+whenIsLeft (Left _)  f = f
+whenIsLeft (Right _) _ = pure ()
+
+whenRightDo :: (Applicative m) => Either l r -> (r -> m ()) -> m ()
+whenRightDo (Right r) f = f r
+whenRightDo (Left _)  _ = pure ()
+
+whenLeftDo :: (Applicative m) => Either l r -> (l -> m ()) -> m ()
+whenLeftDo (Left l)  f = f l
+whenLeftDo (Right _) _ = pure ()
diff --git a/src/Errors.hs b/src/Errors.hs
new file mode 100644
--- /dev/null
+++ b/src/Errors.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Errors
+  ( module X
+  , catchM
+  ) where
+
+import           Control.Monad.Catch as X (Exception (..), MonadCatch,
+                                           MonadThrow (..))
+import qualified Control.Monad.Catch as E (catch)
+
+catchM :: (MonadCatch m, Exception e) => m a -> (e -> m a) -> m a
+catchM = E.catch
diff --git a/src/FilePaths.hs b/src/FilePaths.hs
new file mode 100644
--- /dev/null
+++ b/src/FilePaths.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+module FilePaths
+    ( module X
+    ) where
+
+import           Data.Bool       (not, (&&))
+import           Data.Eq         ((/=), (==))
+import           Data.List       (isInfixOf, null)
+import           Data.Maybe
+import qualified System.FilePath as FilePath
+
+import           Data.Validity
+
+import           Path            as X
+import           Path.Internal
+import           Path.IO         as X
+
+instance Validity (Path Abs File) where
+  isValid p@(Path fp)
+    =  FilePath.isAbsolute fp
+    && not (FilePath.hasTrailingPathSeparator fp)
+    && FilePath.isValid fp
+    && not (".." `isInfixOf` fp)
+    && (parseAbsFile fp == Just p)
+
+instance Validity (Path Rel File) where
+  isValid p@(Path fp)
+    =  FilePath.isRelative fp
+    && not (FilePath.hasTrailingPathSeparator fp)
+    && FilePath.isValid fp
+    && fp /= "."
+    && fp /= ".."
+    && not (".." `isInfixOf` fp)
+    && (parseRelFile fp == Just p)
+
+instance Validity (Path Abs Dir) where
+  isValid p@(Path fp)
+    =  FilePath.isAbsolute fp
+    && FilePath.hasTrailingPathSeparator fp
+    && FilePath.isValid fp
+    && not (".." `isInfixOf` fp)
+    && (parseAbsDir fp == Just p)
+
+instance Validity (Path Rel Dir) where
+  isValid p@(Path fp)
+    =  FilePath.isRelative fp
+    && FilePath.hasTrailingPathSeparator fp
+    && FilePath.isValid fp
+    && not (null fp)
+    && fp /= "."
+    && fp /= ".."
+    && not (".." `isInfixOf` fp)
+    && (parseRelDir fp == Just p)
+
diff --git a/src/Functor.hs b/src/Functor.hs
new file mode 100644
--- /dev/null
+++ b/src/Functor.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Functor
+  ( Functor(..)
+  , ($>)
+  , (<$>)
+  , void
+  ) where
+
+import           Data.Functor (Functor (..), void, ($>), (<$>))
diff --git a/src/IOString.hs b/src/IOString.hs
new file mode 100644
--- /dev/null
+++ b/src/IOString.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE NoImplicitPrelude    #-}
+{-# LANGUAGE Trustworthy          #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module IOString
+    ( IOString
+    , writeFile
+    , readFile
+    , appendFile
+    , putStr
+    , putStrLn
+    , putText
+    , putTextLn
+    , putLText
+    , putLTextLn
+    , FilePath
+    ) where
+
+import qualified Base
+
+import           Data.Function              ((.), ($))
+import           GHC.IO                     (FilePath)
+
+import           Control.Monad.IO.Class     (MonadIO, liftIO)
+import qualified Data.ByteString.Char8      as BS
+import qualified Data.ByteString.Lazy.Char8 as BL
+
+import qualified Data.Text                  as T
+import qualified Data.Text.IO               as T
+
+import qualified Data.Text.Lazy             as TL
+import qualified Data.Text.Lazy.IO          as TL
+
+import           Path
+
+class IOString s where
+    iosWriteFile  :: FilePath -> s -> Base.IO ()
+    iosReadFile   :: FilePath -> Base.IO s
+    iosAppendFile :: FilePath -> s -> Base.IO ()
+    iosPutStr     :: s -> Base.IO ()
+    iosPutStrLn   :: s -> Base.IO ()
+
+instance IOString T.Text where
+    iosWriteFile   = T.writeFile
+    iosReadFile    = T.readFile
+    iosAppendFile  = T.appendFile
+    iosPutStr      = T.putStr
+    iosPutStrLn    = T.putStrLn
+
+instance IOString TL.Text where
+    iosWriteFile   = TL.writeFile
+    iosReadFile    = TL.readFile
+    iosAppendFile  = TL.appendFile
+    iosPutStr      = TL.putStr
+    iosPutStrLn    = TL.putStrLn
+
+instance IOString BS.ByteString where
+    iosWriteFile   = BS.writeFile
+    iosReadFile    = BS.readFile
+    iosAppendFile  = BS.appendFile
+    iosPutStr      = BS.putStr
+    iosPutStrLn    = BS.putStrLn
+
+instance IOString BL.ByteString where
+    iosWriteFile   = BL.writeFile
+    iosReadFile    = BL.readFile
+    iosAppendFile  = BL.appendFile
+    iosPutStr      = BL.putStr
+    iosPutStrLn    = BL.putStrLn
+
+instance IOString [Base.Char] where
+    iosWriteFile   = Base.writeFile
+    iosReadFile    = Base.readFile
+    iosAppendFile  = Base.appendFile
+    iosPutStr      = Base.putStr
+    iosPutStrLn    = Base.putStrLn
+
+writeFile :: (IOString s, MonadIO m) => (Path Abs File) -> s -> m ()
+writeFile p s = liftIO $ iosWriteFile (toFilePath p) s
+
+readFile :: (IOString s, MonadIO m) => (Path Abs File) -> m s
+readFile = liftIO . iosReadFile . toFilePath
+
+appendFile :: (IOString s, MonadIO m) => (Path Abs File) -> s -> m ()
+appendFile p s = liftIO $ iosAppendFile (toFilePath p) s
+
+putStr :: (IOString s, MonadIO m) => s -> m ()
+putStr = liftIO . iosPutStr
+
+putStrLn :: (IOString s, MonadIO m) => s -> m ()
+putStrLn = liftIO . iosPutStrLn
+
+-- For forcing type inference
+putText :: MonadIO m => T.Text -> m ()
+putText = putStr
+{-# SPECIALIZE putText :: T.Text -> Base.IO () #-}
+
+putTextLn :: MonadIO m => T.Text -> m ()
+putTextLn = putStrLn
+{-# SPECIALIZE putText :: T.Text -> Base.IO () #-}
+
+putLText :: MonadIO m => TL.Text -> m ()
+putLText = putStr
+{-# SPECIALIZE putLText :: TL.Text -> Base.IO () #-}
+
+putLTextLn :: MonadIO m => TL.Text -> m ()
+putLTextLn = putStrLn
+{-# SPECIALIZE putLText :: TL.Text -> Base.IO () #-}
+
+
+
diff --git a/src/Introduction.hs b/src/Introduction.hs
new file mode 100644
--- /dev/null
+++ b/src/Introduction.hs
@@ -0,0 +1,184 @@
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE ExplicitNamespaces    #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NoImplicitPrelude     #-}
+{-# LANGUAGE Trustworthy           #-}
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+module Introduction
+  ( module X
+  , module Base
+  , applyN
+  , show
+
+  , SText
+  , LText
+  , SByteString
+  , LByteString
+  ) where
+
+import           Bool                      as X
+import           Concurrency               as X
+import           Debug                     as X
+import           Either                    as X
+import           Errors                    as X
+import           FilePaths                 as X
+import           Functor                   as X
+import           IOString                  as X
+import           List                      as X
+import           Monad                     as X
+
+import           Base                      as Base hiding (appendFile, putStr,
+                                                    putStrLn, readFile, show,
+                                                    writeFile)
+
+import           Data.String               as X (String)
+
+-- Maybe'ized version of partial functions
+import           Safe                      as X (atDef, atMay, foldl1May,
+                                                 foldr1May, headDef, headMay,
+                                                 initDef, initMay, initSafe,
+                                                 lastDef, lastMay, tailDef,
+                                                 tailMay, tailSafe)
+
+-- Applicatives
+import           Control.Applicative       as X (Alternative (..),
+                                                 Applicative (..), Const (..),
+                                                 ZipList (..), liftA, liftA2,
+                                                 liftA3, optional, (<**>))
+
+-- Base typeclasses
+import           Data.Data                 as X (Data (..))
+import           Data.Eq                   as X (Eq (..))
+import           Data.Foldable             as X hiding (foldl1, foldr1)
+import           Data.Functor.Identity     as X
+import           Data.Monoid               as X
+import           Data.Ord                  as X
+import           Data.Traversable          as X
+
+import           Data.RelativeValidity     as X
+import           Data.Validity             as X
+import           Data.Validity.Containers  as X ()
+
+-- Deepseq
+import           Control.DeepSeq           as X (NFData (..), deepseq, force,
+                                                 ($!!))
+
+-- Data structures
+import           Data.List                 as X (break, cycle, drop, dropWhile,
+                                                 filter, group, inits,
+                                                 intercalate, intersperse,
+                                                 isPrefixOf, iterate, map, map,
+                                                 permutations, repeat,
+                                                 replicate, reverse, scanl,
+                                                 scanr, sort, sortBy, splitAt,
+                                                 subsequences, tails, take,
+                                                 takeWhile, transpose, unfoldr,
+                                                 zip, zipWith)
+import           Data.Tuple                as X
+
+import           Data.IntMap               as X (IntMap)
+import           Data.IntSet               as X (IntSet)
+import           Data.Map                  as X (Map)
+import           Data.Sequence             as X (Seq)
+import           Data.Set                  as X (Set)
+
+import           Data.Proxy                as X (Proxy (..))
+
+import           Data.Typeable             as X (TypeRep, Typeable, cast, eqT,
+                                                 typeRep)
+
+import           Data.Type.Coercion        as X (Coercion (..), coerceWith)
+
+import           Data.Type.Equality        as X ((:~:) (..), type (==),
+                                                 castWith, gcastWith, sym,
+                                                 trans)
+
+import           Data.Void                 as X (Void, absurd, vacuous)
+
+-- Monad transformers
+import           Control.Monad.State       as X (MonadState, State, StateT,
+                                                 evalState, evalStateT,
+                                                 execState, execStateT, get,
+                                                 gets, modify, put, runState,
+                                                 runStateT, withState)
+
+import           Control.Monad.Reader      as X (MonadReader, Reader, ReaderT,
+                                                 ask, asks, local, runReader,
+                                                 runReaderT)
+
+import           Control.Monad.Writer      as X (MonadWriter, Writer, WriterT,
+                                                 execWriter, execWriterT,
+                                                 listen, pass, runWriter,
+                                                 runWriterT, tell, writer)
+
+import           Control.Monad.Except      as X (Except, ExceptT, MonadError,
+                                                 catchError, mapExcept,
+                                                 mapExceptT, runExcept,
+                                                 runExceptT, throwError,
+                                                 withExceptT)
+
+import           Control.Monad.Base        as X (MonadBase)
+import           Control.Monad.IO.Class    as X (MonadIO, liftIO)
+import           Control.Monad.Trans.Class as X (lift)
+
+-- Base types
+import           Data.Bits                 as X
+import           Data.Bool                 as X hiding (bool)
+import           Data.Char                 as X (chr)
+import           Data.Complex              as X
+import           Data.Either               as X
+import           Data.Int                  as X
+import           Data.Maybe                as X hiding (fromJust)
+import           Data.Word                 as X
+
+import           Data.Function             as X (const, fix, flip, id, on, ($),
+                                                 (.))
+
+-- Genericss
+import           GHC.Generics              as X (Generic)
+
+-- ByteString
+import           Data.ByteString           as X (ByteString)
+import qualified Data.ByteString
+import qualified Data.ByteString.Lazy
+
+-- Text
+import           Data.Text                 as X (Text)
+import qualified Data.Text
+import qualified Data.Text.IO
+import qualified Data.Text.Lazy
+import           Text.Show                 (Show (..))
+
+import           Data.Text.Lazy            (fromStrict, toStrict)
+
+import           Data.String               as X (IsString)
+
+-- Printf
+import           Text.Printf               as X (PrintfArg, hPrintf, printf)
+
+-- IO
+import           System.Exit               as X
+--import System.Info as X
+import           System.Environment        as X (getArgs)
+import           System.IO                 as X (Handle)
+
+-- ST
+import           Control.Monad.ST          as X
+
+import           Foreign.Storable          as X (Storable)
+
+-- Read instances hiding unsafe builtins (read)
+import           Text.Read                 as X (Read, readEither, readMaybe,
+                                                 reads)
+
+-- Type synonymss
+type SText = Data.Text.Text
+type LText = Data.Text.Lazy.Text
+
+type SByteString = Data.ByteString.ByteString
+type LByteString = Data.ByteString.Lazy.ByteString
+
+applyN :: Int -> (a -> a) -> a -> a
+applyN n f = X.foldr (.) id (X.replicate n f)
diff --git a/src/List.hs b/src/List.hs
new file mode 100644
--- /dev/null
+++ b/src/List.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Safe              #-}
+
+module List
+    ( ordNub
+    , sortOn
+    , uncons
+    , snoc
+    , windows
+    , chunksOf
+    ) where
+
+import           Data.Bool     (otherwise)
+import           Data.Function ((.))
+import           Data.Int      (Int)
+import           Data.List     (drop, length, sortBy, take, (++))
+import           Data.Maybe    (Maybe (..))
+import           Data.Ord      (Ord (..), comparing)
+import qualified Data.Set      as Set
+
+sortOn :: (Ord o) => (a -> o) -> [a] -> [a]
+sortOn = sortBy . comparing
+
+-- | Fast @nub@ if the contents of the list are orderable
+--
+-- O(n * log n)
+ordNub :: (Ord a) => [a] -> [a]
+ordNub l = go Set.empty l
+  where
+    go _ []     = []
+    go s (x:xs) =
+      if x `Set.member` s
+      then go s xs
+      else x : go (Set.insert x s) xs
+
+-- | Deconstruct a list into its first element the rest of the list
+-- This will evaluate to @Nothing@ if the list is empty.
+uncons :: [a] -> Maybe (a, [a])
+uncons []     = Nothing
+uncons (x:xs) = Just (x, xs)
+
+-- | @(:)@, appending instead of prepending
+-- @(:)@ is sometimes called cons, so when we append instead of prepend, we call the function @snoc@
+-- Note that this has an O(length list) time complexity
+snoc :: [a] -> a -> [a]
+snoc as a = as ++ [a]
+
+-- | Find all @i@-sized windows in a list
+windows :: Int -> [a] -> [[a]]
+windows _ [] = []
+windows i xss@(_:xs)
+    | length xss >= i = (take i xss) : windows i xs
+    | otherwise       = []
+
+-- | Takes chunks of a given size, the last chunk may be smaller but not empty.
+chunksOf :: Int -> [a] -> [[a]]
+chunksOf _ [] = []
+chunksOf i xs
+    | length xs >= i = take i xs : chunksOf i (drop i xs)
+    | otherwise = [xs]
diff --git a/src/Monad.hs b/src/Monad.hs
new file mode 100644
--- /dev/null
+++ b/src/Monad.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Safe              #-}
+
+module Monad (
+    Monad((>>=), return)
+  , MonadPlus(..)
+
+  , (=<<)
+  , (>=>)
+  , (<=<)
+  , forever
+
+  , join
+  , mfilter
+  , filterM
+  , mapAndUnzipM
+  , zipWithM
+  , zipWithM_
+  , foldM
+  , foldM_
+  , replicateM
+  , replicateM_
+  , concatMapM
+
+  , guard
+  , when
+  , unless
+
+  , liftM
+  , liftM2
+  , liftM3
+  , liftM4
+  , liftM5
+  , ap
+  ) where
+
+import           Data.List     (concat)
+
+import           Control.Monad hiding ((<$!>))
+
+concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
+concatMapM f xs = liftM concat (mapM f xs)
diff --git a/src/Unsafe.hs b/src/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Unsafe.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Unsafe            #-}
+
+module Unsafe (
+  unsafeHead,
+  unsafeTail,
+  unsafeInit,
+  unsafeLast,
+  unsafeFromJust,
+  unsafeIndex,
+) where
+
+import           Base       (Int)
+import qualified Data.List  as List
+import qualified Data.Maybe as Maybe
+
+{-# WARNING unsafeHead "An unsafe function: 'unsafehead' remains in code" #-}
+unsafeHead :: [a] -> a
+unsafeHead = List.head
+
+{-# WARNING unsafeTail "An unsafe function: 'unsafeTail' remains in code" #-}
+unsafeTail :: [a] -> [a]
+unsafeTail = List.tail
+
+{-# WARNING unsafeInit "An unsafe function: 'unsafeInit' remains in code" #-}
+unsafeInit :: [a] -> [a]
+unsafeInit = List.init
+
+{-# WARNING unsafeLast "An unsafe function: 'unsafeLast' remains in code" #-}
+unsafeLast :: [a] -> a
+unsafeLast = List.last
+
+{-# WARNING unsafeFromJust "An unsafe function: 'unsafeFromJust' remains in code" #-}
+unsafeFromJust :: Maybe.Maybe a -> a
+unsafeFromJust = Maybe.fromJust
+
+{-# WARNING unsafeIndex "An unsafe function: 'unsafeIndex' remains in code" #-}
+unsafeIndex :: [a] -> Int -> a
+unsafeIndex = (List.!!)
