diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,9 +0,0 @@
-import Distribution.PackageDescription
-import Distribution.Simple
-import Distribution.Simple.LocalBuildInfo
-import Distribution.Simple.Setup
-
-import System.Process
-
-main :: IO ()
-main = defaultMain
diff --git a/bizzlelude.cabal b/bizzlelude.cabal
--- a/bizzlelude.cabal
+++ b/bizzlelude.cabal
@@ -1,15 +1,15 @@
+Cabal-Version:       3.8
 Name:                bizzlelude
-Version:             1.1.0
-Cabal-version:       >=1.22.0
-License:             BSD3
+Version:             4.20.2.0.3
+License:             BSD-3-Clause
 License-File:        LICENSE.txt
 Author:              Jason Bertsche
 Maintainer:          jason.bertsche@gmail.com
-Homepage:            http://github.com/TheBizzle
+Homepage:            https://github.com/TheBizzle
 Category:            Prelude
 Synopsis:            A lousy Prelude replacement by a lousy dude
-Description:         A lousy Prelude replacement by a lousy dude.  Imports common things while trying to avoid importing things could cause naming conflicts.  Favors `Text` over `String`.  Wants using `IO` to be painful.
-Stability:           Experimental
+Description:         A lousy Prelude replacement by a lousy dude.  Imports common things while trying to avoid importing things that could cause naming conflicts.  Favors `Text` over `String`.  Wants using `IO` to be painful.
+Stability:           Stable
 Build-type:          Simple
 
 source-repository head
@@ -18,15 +18,285 @@
 
 library
   hs-source-dirs:   src/main
-  exposed-modules:  Prelude
+  exposed-modules:  Prelude, Data.Text.Word
   default-extensions: OverloadedStrings
-  default-language: Haskell2010
+  default-language: GHC2024
+  other-modules: External, Misc, Tuple2, Tuple3, Tuple4
   GHC-Options:
     -Wall
+    -Wcompat
+    -Wincomplete-record-updates
+    -Wincomplete-uni-patterns
+    -Wmissing-import-lists
+    -Wredundant-constraints
     -fno-warn-name-shadowing
     -funbox-strict-fields
   Build-depends:
-    base-noprelude >= 4.8    && < 5,
-    containers     >= 0.5.7  && < 0.6.0,
-    directory      >= 1.3.0  && < 1.4.0,
-    text           >= 1.2.2  && < 1.3.0
+    , base == 4.20.2.0
+    , bytestring     >= 0.12.0 && < 0.13
+    , containers     >= 0.7    && < 0.8
+    , directory      >= 1.3.0  && < 1.4
+    , mtl            >= 2.3.0  && < 2.4
+    , pcre-light     >= 0.4.0  && < 0.5
+    , text           >= 2.1.0  && < 2.2
+    , validation     >= 1.1.0  && < 1.2
+
+  -- The below is copied from the `exposed-modules` in 'base' (modulo `prelude`)
+  -- https://gitlab.haskell.org/ghc/ghc/-/blob/master/libraries/base/base.cabal.in
+  Reexported-Modules:
+    , Control.Applicative
+    , Control.Arrow
+    , Control.Category
+    , Control.Concurrent
+    , Control.Concurrent.Chan
+    , Control.Concurrent.MVar
+    , Control.Concurrent.QSem
+    , Control.Concurrent.QSemN
+    , Control.Exception
+    , Control.Exception.Annotation
+    , Control.Exception.Backtrace
+    , Control.Exception.Base
+    , Control.Exception.Context
+    , Control.Monad
+    , Control.Monad.Fail
+    , Control.Monad.Fix
+    , Control.Monad.Instances
+    , Control.Monad.IO.Class
+    , Control.Monad.ST
+    , Control.Monad.ST.Lazy
+    , Control.Monad.ST.Lazy.Safe
+    , Control.Monad.ST.Lazy.Unsafe
+    , Control.Monad.ST.Safe
+    , Control.Monad.ST.Strict
+    , Control.Monad.ST.Unsafe
+    , Control.Monad.Zip
+    , Data.Array.Byte
+    , Data.Bifoldable
+    , Data.Bifoldable1
+    , Data.Bifunctor
+    , Data.Bitraversable
+    , Data.Bits
+    , Data.Bool
+    , Data.Char
+    , Data.Coerce
+    , Data.Complex
+    , Data.Data
+    , Data.Dynamic
+    , Data.Either
+    , Data.Enum
+    , Data.Eq
+    , Data.Fixed
+    , Data.Foldable
+    , Data.Foldable1
+    , Data.Function
+    , Data.Functor
+    , Data.Functor.Classes
+    , Data.Functor.Compose
+    , Data.Functor.Const
+    , Data.Functor.Contravariant
+    , Data.Functor.Identity
+    , Data.Functor.Product
+    , Data.Functor.Sum
+    , Data.Int
+    , Data.IORef
+    , Data.Ix
+    , Data.Kind
+    , Data.List
+    , Data.List.NonEmpty
+    , Data.Maybe
+    , Data.Monoid
+    , Data.Ord
+    , Data.Proxy
+    , Data.Ratio
+    , Data.Semigroup
+    , Data.STRef
+    , Data.STRef.Lazy
+    , Data.STRef.Strict
+    , Data.String
+    , Data.Traversable
+    , Data.Tuple
+    , Data.Typeable
+    , Data.Type.Bool
+    , Data.Type.Coercion
+    , Data.Type.Equality
+    , Data.Type.Ord
+    , Data.Unique
+    , Data.Version
+    , Data.Void
+    , Data.Word
+    , Debug.Trace
+    , Foreign
+    , Foreign.C
+    , Foreign.C.ConstPtr
+    , Foreign.C.Error
+    , Foreign.Concurrent
+    , Foreign.C.String
+    , Foreign.C.Types
+    , Foreign.ForeignPtr
+    , Foreign.ForeignPtr.Safe
+    , Foreign.ForeignPtr.Unsafe
+    , Foreign.Marshal
+    , Foreign.Marshal.Alloc
+    , Foreign.Marshal.Array
+    , Foreign.Marshal.Error
+    , Foreign.Marshal.Pool
+    , Foreign.Marshal.Safe
+    , Foreign.Marshal.Unsafe
+    , Foreign.Marshal.Utils
+    , Foreign.Ptr
+    , Foreign.Safe
+    , Foreign.StablePtr
+    , Foreign.Storable
+    , GHC.Arr
+    , GHC.ArrayArray
+    , GHC.Base
+    , GHC.Bits
+    , GHC.ByteOrder
+    , GHC.Char
+    , GHC.Clock
+    , GHC.Conc
+    , GHC.Conc.IO
+    , GHC.Conc.Signal
+    , GHC.Conc.Sync
+    , GHC.ConsoleHandler
+    , GHC.Constants
+    , GHC.Desugar
+    , GHC.Encoding.UTF8
+    , GHC.Enum
+    , GHC.Environment
+    , GHC.Err
+    , GHC.Event.TimeOut
+    , GHC.Exception
+    , GHC.Exception.Type
+    , GHC.ExecutionStack
+    , GHC.Exts
+    , GHC.Fingerprint
+    , GHC.Fingerprint.Type
+    , GHC.Float
+    , GHC.Float.ConversionUtils
+    , GHC.Float.RealFracMethods
+    , GHC.Foreign
+    , GHC.ForeignPtr
+    , GHC.Generics
+    , GHC.GHCi
+    , GHC.GHCi.Helpers
+    , GHC.InfoProv
+    , GHC.Int
+    , GHC.Integer
+    , GHC.Integer.Logarithms
+    , GHC.IO
+    , GHC.IOArray
+    , GHC.IO.Buffer
+    , GHC.IO.BufferedIO
+    , GHC.IO.Device
+    , GHC.IO.Encoding
+    , GHC.IO.Encoding.CodePage
+    , GHC.IO.Encoding.Failure
+    , GHC.IO.Encoding.Iconv
+    , GHC.IO.Encoding.Latin1
+    , GHC.IO.Encoding.Types
+    , GHC.IO.Encoding.UTF16
+    , GHC.IO.Encoding.UTF32
+    , GHC.IO.Encoding.UTF8
+    , GHC.IO.Exception
+    , GHC.IO.FD
+    , GHC.IO.Handle
+    , GHC.IO.Handle.FD
+    , GHC.IO.Handle.Internals
+    , GHC.IO.Handle.Lock
+    , GHC.IO.Handle.Text
+    , GHC.IO.Handle.Types
+    , GHC.IO.IOMode
+    , GHC.IORef
+    , GHC.IO.StdHandles
+    , GHC.IO.SubSystem
+    , GHC.IO.Unsafe
+    , GHC.IsList
+    , GHC.Ix
+    , GHC.List
+    , GHC.Maybe
+    , GHC.MVar
+    , GHC.Natural
+    , GHC.Num
+    , GHC.Num.BigNat
+    , GHC.Num.Integer
+    , GHC.Num.Natural
+    , GHC.OldList
+    , GHC.OverloadedLabels
+    , GHC.Profiling
+    , GHC.Ptr
+    , GHC.Read
+    , GHC.Real
+    , GHC.Records
+    , GHC.ResponseFile
+    , GHC.RTS.Flags
+    , GHC.Show
+    , GHC.ST
+    , GHC.Stable
+    , GHC.StableName
+    , GHC.Stack
+    , GHC.Stack.CCS
+    , GHC.Stack.CloneStack
+    , GHC.Stack.Types
+    , GHC.StaticPtr
+    , GHC.Stats
+    , GHC.Storable
+    , GHC.STRef
+    , GHC.TopHandler
+    , GHC.TypeError
+    , GHC.TypeLits
+    , GHC.TypeNats
+    , GHC.Unicode
+    , GHC.Weak
+    , GHC.Weak.Finalize
+    , GHC.Word
+    , Numeric
+    , Numeric.Natural
+    , System.Console.GetOpt
+    , System.CPUTime
+    , System.Environment
+    , System.Environment.Blank
+    , System.Exit
+    , System.Info
+    , System.IO
+    , System.IO.Error
+    , System.IO.Unsafe
+    , System.Mem
+    , System.Mem.StableName
+    , System.Mem.Weak
+    , System.Posix.Internals
+    , System.Posix.Types
+    , System.Timeout
+    , Text.ParserCombinators.ReadP
+    , Text.ParserCombinators.ReadPrec
+    , Text.Printf
+    , Text.Read
+    , Text.Read.Lex
+    , Text.Show
+    , Text.Show.Functions
+    , Type.Reflection
+    , Type.Reflection.Unsafe
+    , Unsafe.Coerce
+
+  if os(windows)
+    Reexported-Modules:
+      , GHC.IO.Encoding.CodePage.API
+      , GHC.IO.Encoding.CodePage.Table
+      , GHC.Conc.Windows
+      , GHC.Conc.WinIO
+      , GHC.Conc.POSIX
+      , GHC.Conc.POSIX.Const
+      , GHC.Windows
+      , GHC.Event.Windows
+      , GHC.Event.Windows.Clock
+      , GHC.Event.Windows.ConsoleEvent
+      , GHC.Event.Windows.FFI
+      , GHC.Event.Windows.ManagedThreadPool
+      , GHC.Event.Windows.Thread
+      , GHC.IO.Handle.Windows
+      , GHC.IO.Windows.Handle
+      , GHC.IO.Windows.Encoding
+      , GHC.IO.Windows.Paths
+  else
+    Reexported-Modules:
+      , GHC.Event
diff --git a/src/main/Data/Text/Word.hs b/src/main/Data/Text/Word.hs
new file mode 100644
--- /dev/null
+++ b/src/main/Data/Text/Word.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Data.Text.Word(center, chunksOf, compareLength, count, drop, dropEnd, findIndex, index, justifyLeft, justifyRight, length, replicate, splitAt, take, takeEnd, unfoldrN) where
+
+import External(($), Bool, Char, fromIntegral, Maybe, Ordering, Text, Word)
+import Misc((&>), map)
+
+import qualified Data.Text as T
+
+
+center :: Word -> Char -> Text -> Text
+center a b c = T.center (fromIntegral a) b c
+
+chunksOf :: Word -> Text -> [Text]
+chunksOf a b = T.chunksOf (fromIntegral a) b
+
+compareLength :: Text -> Word -> Ordering
+compareLength a b = T.compareLength a (fromIntegral b)
+
+count :: Text -> Text -> Word
+count a b = fromIntegral $ T.count a b
+
+dropEnd :: Word -> Text -> Text
+dropEnd a b = T.dropEnd (fromIntegral a) b
+
+drop :: Word -> Text -> Text
+drop a b = T.drop (fromIntegral a) b
+
+findIndex :: (Char -> Bool) -> Text -> Maybe Word
+findIndex f = (T.findIndex f) &> (map fromIntegral)
+
+index :: Text -> Word -> Char
+index a b = T.index a (fromIntegral b)
+
+justifyLeft :: Word -> Char -> Text -> Text
+justifyLeft a b c = T.justifyLeft (fromIntegral a) b c
+
+justifyRight :: Word -> Char -> Text -> Text
+justifyRight a b c = T.justifyRight (fromIntegral a) b c
+
+length :: Text -> Word
+length = T.length &> fromIntegral
+
+replicate :: Word -> Text -> Text
+replicate a b = T.replicate (fromIntegral a) b
+
+splitAt :: Word -> Text -> (Text, Text)
+splitAt a b = T.splitAt (fromIntegral a) b
+
+takeEnd :: Word -> Text -> Text
+takeEnd a b = T.takeEnd (fromIntegral a) b
+
+take :: Word -> Text -> Text
+take a b = T.take (fromIntegral a) b
+
+unfoldrN :: Word -> (a -> Maybe (Char, a)) -> a -> Text
+unfoldrN a f c = T.unfoldrN (fromIntegral a) f c
diff --git a/src/main/External.hs b/src/main/External.hs
new file mode 100644
--- /dev/null
+++ b/src/main/External.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module External(module Control.Arrow, module Control.Applicative, module Control.Monad, module Control.Monad.IO.Class, module Control.Monad.State, module Data.Bifoldable, module Data.Bifunctor, module Data.Bool, module Data.ByteString, module Data.Char, module Data.Either, module Data.Eq, module Data.Foldable, module Data.Foldable1, module Data.Function, module Data.Functor, module Data.Int, module Data.IntSet, module Data.List, module Data.List.NonEmpty, module Data.Map, module Data.Maybe, module Data.Monoid, module Data.Ord, module Data.Semigroup, module Data.Set, module Data.Text, module Data.Traversable, module Data.Tuple, module Data.Type.Equality, module Data.Validation, module Data.Void, module Data.Word, module Debug.Trace, module GHC.Base, module GHC.Enum, module GHC.Err, module GHC.Float, module GHC.IO, module GHC.Num, module GHC.Real, module GHC.Show, module Numeric, module System.IO.Error, module Text.Read) where
+
+import Control.Arrow((&&&), (***))
+import Control.Applicative((<**>), Alternative((<|>), many, some), Applicative((<*>), (<*), (*>), pure), liftA2, optional)
+import Control.Monad((=<<), filterM, foldM, foldM_, forM, forM_, guard, join, mapM, mapM_, Monad((>>), (>>=), return), MonadPlus(), sequence, sequence_, unless, when)
+import Control.Monad.IO.Class(liftIO)
+import Control.Monad.State(evalState, execState, mapState, runState, State, withState)
+
+import Data.Bifoldable(Bifoldable, bifold, bifoldMap, bimapM_)
+import Data.Bifunctor(Bifunctor(bimap, first, second))
+import Data.Bool(Bool(False, True), (&&), (||), not, otherwise)
+import Data.ByteString(ByteString)
+import Data.Char(Char, digitToInt, intToDigit)
+import Data.Either(Either(Left, Right), either, lefts, isLeft, isRight, partitionEithers, rights)
+import Data.Eq(Eq((==), (/=)))
+import Data.Foldable(and, any, all, Foldable(elem, fold, foldMap, foldr, foldr', foldl', null, maximum, minimum, sum, product), find, foldlM, foldrM, for_, maximumBy, minimumBy, or, sequenceA_)
+import Data.Foldable1(foldl1', foldr1)
+import Data.Function(($), (.), const, flip, id, on)
+import Data.Functor((<$), (<$>), ($>), Functor(fmap), void)
+import Data.Int(Int, Int8, Int16, Int32, Int64)
+import Data.IntSet(IntSet)
+import Data.List((++))
+import Data.List.NonEmpty(nonEmpty, NonEmpty((:|)))
+import Data.Map(Map)
+import Data.Maybe(catMaybes, fromMaybe, isJust, isNothing, listToMaybe, maybe, maybeToList, Maybe(Just, Nothing))
+import Data.Monoid(Monoid(mappend, mempty))
+import Data.Ord(Ord((<), (<=), (>), (>=), compare, max, min), Ordering(EQ, GT, LT))
+import Data.Semigroup(Semigroup((<>)))
+import Data.Set(Set)
+import Data.Text(lines, Text, unlines, unwords, words)
+import Data.Traversable(for, sequenceA, Traversable, traverse)
+import Data.Tuple(curry, fst, snd, swap, uncurry)
+import Data.Type.Equality(type (~))
+import Data.Word(Word, Word8, Word16, Word32, Word64)
+import Data.Validation(bindValidation, validation, Validation(Failure, Success))
+import Data.Void(Void)
+
+import Debug.Trace(trace, traceEvent, traceEventIO, traceId, traceIO, traceM, traceMarker, traceMarkerIO, traceShow, traceShowId, traceShowM, traceStack)
+
+import GHC.Base(($!), seq, String)
+import GHC.Enum(Bounded, boundedEnumFrom, boundedEnumFromThen, Enum, enumFrom, enumFromThen, enumFromThenTo, enumFromTo, fromEnum, fromEnumError, maxBound, minBound, pred, predError, succ, succError, toEnum, toEnumError)
+
+import GHC.Err(undefined)
+import GHC.Float(Double, Float)
+import GHC.IO(FilePath, IO)
+import GHC.Num(Integer, Num((+), (-), (*), abs, signum, fromInteger, negate), subtract)
+import GHC.Real((^), (^^), Fractional(recip, fromRational), fromIntegral, Integral(quot, rem, div, mod, quotRem, divMod, toInteger), RealFrac(properFraction, truncate, round, ceiling, floor), Real(toRational), realToFrac)
+import GHC.Show(Show(show))
+
+import Numeric(Floating, pi, exp, log, sqrt, (**), logBase, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, showFFloat)
+
+import System.IO.Error(IOError, ioError, userError)
+
+import Text.Read(read, Read, readMaybe)
diff --git a/src/main/Misc.hs b/src/main/Misc.hs
new file mode 100644
--- /dev/null
+++ b/src/main/Misc.hs
@@ -0,0 +1,133 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+module Misc((|>), (&>), (&>=), (>>>), (>=>), (/#), aempty, asString, asPath, asText, showText, concat, error, failOrM, fromEither, map, pam, (<&>), cartProduct, regexMatch, groupOn, length, orElse, return', scalaGroupBy, putStrFlush, traceLabel, unsafeRead, listDirsRecursively, uncurry5, uncurry6) where
+
+import External
+
+import Data.Text.Encoding(decodeUtf8, encodeUtf8)
+
+import GHC.Real(Fractional((/)))
+
+import qualified Control.Applicative   as Apply
+import qualified Control.Arrow         as CArrow
+import qualified Control.Monad         as CMonad
+import qualified Data.Either           as Either
+import qualified Data.Foldable         as Foldable
+import qualified Data.List             as List
+import qualified Data.List.NonEmpty    as NE
+import qualified Data.Text             as Text
+import qualified Data.Text.IO          as TIO
+import qualified Data.Text.Read        as DTR
+import qualified GHC.Err               as Err
+import qualified System.Directory      as SD
+import qualified System.IO             as SIO
+import qualified Text.Regex.PCRE.Light as PCRE
+
+(/#) :: (Real a, Real b) => a -> b -> Double
+a /# b = (realToFrac a) / (realToFrac b)
+
+(|>) :: a -> (a -> b) -> b
+a |> f = f a
+
+(&>), (>>>) :: (a -> b) -> (b -> c) -> (a -> c)
+(>>>) = (CArrow.>>>)
+(&>)  = (>>>)
+
+(&>=), (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
+(>=>) = (CMonad.>=>)
+(&>=) = (>=>)
+
+infixl 2 >>>, >=>
+infixl 1 |>
+
+aempty :: Apply.Alternative f => f a
+aempty = Apply.empty
+
+asString :: Text -> String
+asString = Text.unpack
+
+asPath :: Text -> FilePath
+asPath = asString
+
+asText :: String -> Text
+asText = Text.pack
+
+showText :: Show a => a -> Text
+showText = show &> asText
+
+concat :: (Foldable t, MonadPlus m) => t (m a) -> m a
+concat = Foldable.msum
+
+error :: Text -> a
+error = asString &> Err.error
+
+map :: (Functor f) => (a -> b) -> f a -> f b
+map = fmap
+
+pam, (<&>) :: Functor f => f a -> (a -> b) -> f b
+pam   = flip map
+(<&>) = flip map
+
+failOrM :: Monad m => Validation f s1 -> (s1 -> m (Validation f s2)) -> m (Validation f s2)
+v `failOrM` vm = validation (Failure &> return) vm v
+
+orElse :: Maybe a -> a -> a
+orElse m x = maybe x id m
+
+length :: Foldable t => t a -> Word
+length = Foldable.length &> fromIntegral
+
+cartProduct :: [a] -> [b] -> [(a, b)]
+cartProduct xs ys = [(x, y) | x <- xs, y <- ys]
+
+regexMatch :: Text -> Text -> Maybe [Text]
+regexMatch regex text = map (map decodeUtf8) matched
+  where
+    compiled = PCRE.compile (encodeUtf8 regex) [PCRE.dotall, PCRE.multiline]
+    matchedL = PCRE.match compiled (encodeUtf8 text) []
+    matched  = map (unsafeNonEmpty &> NE.tail) matchedL
+
+unsafeNonEmpty :: [a] -> NonEmpty a
+unsafeNonEmpty = NE.nonEmpty &> maybe (error "Impossible") id
+
+fromEither :: Either a a -> a
+fromEither = either id id
+
+groupOn :: Ord criterion => (item -> criterion) -> [item] -> [NonEmpty item]
+groupOn f = sort &> group &> (map $ unsafeNonEmpty)
+  where
+    sort  = List.sortBy (compare `on` f)
+    group = List.groupBy ((==) `on` f)
+
+return' :: (Monad m) => a -> m a
+return' = (return $!)
+
+scalaGroupBy :: Ord criterion => (item -> criterion) -> [item] -> [(criterion, NonEmpty item)]
+scalaGroupBy f = (groupOn f) &> pair
+  where
+    pair  = tee $ NE.head &> f
+    tee f = map $ f &&& id
+
+-- Hack to make GHCI print this before the prompt --Jason B. (2/20/17)
+putStrFlush :: Text -> IO ()
+putStrFlush x = (TIO.putStr x) >>= (const $ SIO.hFlush SIO.stdout)
+
+traceLabel :: (Show a) => Text -> a -> a
+traceLabel label a = traceShow (label <> ": " <> (showText a)) a
+
+unsafeRead :: Integral a => Text -> a
+unsafeRead = DTR.decimal &> (Either.either (error "Well, that read *was* unsafe...") id) &> fst
+
+listDirsRecursively :: FilePath -> IO [FilePath]
+listDirsRecursively filepath =
+  do
+    paths    <- SD.listDirectory filepath
+    dirs     <- paths |> ((map $ \x -> filepath <> "/" <> x) &> (filterM SD.doesDirectoryExist))
+    children <- mapM listDirsRecursively dirs
+    return $ dirs <> (concat children)
+
+uncurry5 :: (a -> b -> c -> d -> e -> f) -> ((a, b, c, d, e) -> f)
+uncurry5 f (a, b, c, d, e) = f a b c d e
+
+uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> ((a, b, c, d, e, f) -> g)
+uncurry6 g (a, b, c, d, e, f) = g a b c d e f
diff --git a/src/main/Prelude.hs b/src/main/Prelude.hs
--- a/src/main/Prelude.hs
+++ b/src/main/Prelude.hs
@@ -1,116 +1,8 @@
-module Prelude((|>), (<&>), asPath, asString, asText, concat, error, groupOn, listDirsRecursively, map, putStrFlush, return', scalaGroupBy, showText, uncurry3, uncurry4, uncurry5, unsafeRead
-              , module Control.Arrow, module Control.Applicative, module Control.Monad, module Data.Bifunctor, module Data.Bool, module Data.Char, module Data.Either, module Data.Eq, module Data.Foldable, module Data.Function, module Data.Functor, module Data.Int, module Data.IntSet, module Data.Map, module Data.Maybe, module Data.Monoid, module Data.Ord, module Data.Set, module Data.Text, module Data.Tuple, module Debug.Trace, module GHC.Base, module GHC.Err, module GHC.Float, module GHC.IO, module GHC.Num, module GHC.Real, module GHC.Show, module Numeric, module System.IO.Error, module Text.Read) where
-
-import Control.Arrow((&&&), (***), (>>>))
-import Control.Applicative(Alternative((<|>)), Applicative((<*>), (<*), (*>), pure))
-import Control.Monad((>=>), filterM, foldM, foldM_, forM, forM_, guard, join, mapM, mapM_, Monad((>>), (>>=), return), MonadPlus(), sequence, sequence_, unless, when)
-
-import Data.Bifunctor(Bifunctor(bimap, first, second))
-import Data.Bool(Bool(False, True), (&&), (||), not, otherwise)
-import Data.Char(Char, digitToInt, intToDigit)
-import Data.Either(Either(Left, Right), either, lefts, isLeft, isRight, partitionEithers, rights)
-import Data.Eq(Eq((==), (/=)))
-import Data.Foldable(Foldable(fold, foldMap, foldr, foldr', foldl, foldl', foldr1, foldl1, null, length, elem, maximum, minimum, sum, product), foldlM, for_, sequenceA_, and, or, any, all, maximumBy, minimumBy, find)
-import Data.Function(($), (.), const, flip, id, on)
-import Data.Functor((<$), (<$>), ($>), Functor(fmap), void)
-import Data.Int(Int, Int8, Int16, Int32, Int64)
-import Data.IntSet(IntSet)
-import Data.Map(Map)
-import Data.Maybe(catMaybes, fromMaybe, isJust, isNothing, maybe, Maybe(Just, Nothing))
-import Data.Monoid((<>), Monoid(mappend, mempty))
-import Data.Ord(Ord((<), (<=), (>), (>=), compare, max, min), Ordering(EQ, GT, LT))
-import Data.Set(Set)
-import Data.Text(lines, Text, unlines, unwords, words)
-import Data.Tuple(curry, fst, snd, swap, uncurry)
-
-import Debug.Trace(trace, traceEvent, traceEventIO, traceId, traceIO, traceM, traceMarker, traceMarkerIO, traceShow, traceShowId, traceShowM, traceStack)
-
-import GHC.Base(($!), seq, String)
-import GHC.Err(undefined)
-import GHC.Float(Double, Float)
-import GHC.IO(FilePath, IO)
-import GHC.Num(Integer, Num((+), (-), (*), abs, signum, fromInteger, negate), subtract)
-import GHC.Real((^), Fractional((/), recip, fromRational), fromIntegral, Integral(quot, rem, div, mod, quotRem, divMod, toInteger), RealFrac(properFraction, truncate, round, ceiling, floor))
-import GHC.Show(Show(show))
-
-import Numeric(Floating, pi, exp, log, sqrt, (**), logBase, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh)
-
-import System.IO.Error(IOError, ioError, userError)
-
-import Text.Read(read)
-
-import qualified Data.Either      as Either
-import qualified Data.Foldable    as Foldable
-import qualified Data.List        as List
-import qualified Data.Text        as Text
-import qualified Data.Text.IO     as TIO
-import qualified Data.Text.Read   as DTR
-import qualified GHC.Err          as Err
-import qualified System.Directory as SD
-import qualified System.IO        as SIO
-
-(|>) :: a -> (a -> b) -> b
-a |> f = f a
-
-asString :: Text -> String
-asString = Text.unpack
-
-asPath :: Text -> FilePath
-asPath = asString
-
-asText :: String -> Text
-asText = Text.pack
-
-showText :: Show a => a -> Text
-showText = show >>> asText
-
-concat :: (Foldable t, MonadPlus m) => t (m a) -> m a
-concat = Foldable.msum
-
-error :: Text -> a
-error = asString >>> Err.error
-
-map :: (Functor f) => (a -> b) -> f a -> f b
-map = fmap
-
-(<&>) :: Functor f => f a -> (a -> b) -> f b
-(<&>) = flip map
-
-groupOn :: Ord criterion => (item -> criterion) -> [item] -> [[item]]
-groupOn f = sort >>> group
-  where
-    sort  = List.sortBy (compare `on` f)
-    group = List.groupBy ((==) `on` f)
-
-return' :: (Monad m) => a -> m a
-return' = (return $!)
-
-scalaGroupBy :: Ord criterion => (item -> criterion) -> [item] -> [(criterion, [item])]
-scalaGroupBy f = (groupOn f) >>> pair
-  where
-    pair  = tee $ List.head >>> f
-    tee f = map $ f &&& id
-
--- Hack to make GHCI print this before the prompt (JAB, 2/20/17)
-putStrFlush :: Text -> IO ()
-putStrFlush x = (TIO.putStr x) >>= (const $ SIO.hFlush SIO.stdout)
-
-unsafeRead :: Integral a => Text -> a
-unsafeRead = DTR.decimal >>> (Either.either (error "Well, that read *was* unsafe...") id) >>> fst
-
-listDirsRecursively :: FilePath -> IO [FilePath]
-listDirsRecursively filepath =
-  do
-    paths    <- SD.listDirectory filepath
-    dirs     <- paths |> ((map $ \x -> filepath <> "/" <> x) >>> (filterM SD.doesDirectoryExist))
-    children <- mapM listDirsRecursively dirs
-    return $ dirs <> (concat children)
-
-uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
-uncurry3 f (a, b, c) = f a b c
-
-uncurry4 :: (a -> b -> c -> d -> e) -> ((a, b, c, d) -> e)
-uncurry4 f (a, b, c, d) = f a b c d
+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+module Prelude(module External, module Misc, module Tuple2, module Tuple3, module Tuple4) where
 
-uncurry5 :: (a -> b -> c -> d -> e -> f) -> ((a, b, c, d, e) -> f)
-uncurry5 f (a, b, c, d, e) = f a b c d e
+import External
+import Misc
+import Tuple2
+import Tuple3
+import Tuple4
diff --git a/src/main/Tuple2.hs b/src/main/Tuple2.hs
new file mode 100644
--- /dev/null
+++ b/src/main/Tuple2.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+module Tuple2(mapFst, mapSnd, mapAll2, mapEach2, mapFstF, mapSndF, tuple2To3a, tuple2To3b, tuple2To3c) where
+
+import External
+
+(<&>) :: Functor f => f a -> (a -> b) -> f b
+(<&>) = flip fmap
+
+mapFst :: (a -> x) -> (a, b) -> (x, b)
+mapFst f (a, b) = (f a, b)
+
+mapSnd :: (b -> x) -> (a, b) -> (a, x)
+mapSnd f (a, b) = (a, f b)
+
+mapAll2 :: (a -> x) -> (a, a) -> (x, x)
+mapAll2 f (a, b) = (f a, f b)
+
+mapEach2 :: (a -> x) -> (b -> y) -> (a, b) -> (x, y)
+mapEach2 f g (a, b) = (f a, g b)
+
+mapFstF :: Functor f => (a -> f x) -> (a, b) -> f (x, b)
+mapFstF f (a, b) = (f a) <&> (\x -> (x, b))
+
+mapSndF :: Functor f => (b -> f x) -> (a, b) -> f (a, x)
+mapSndF f (a, b) = (f b) <&> (\x -> (a, x))
+
+tuple2To3a :: (a, b) -> x -> (x, a, b)
+tuple2To3a (a, b) x = (x, a, b)
+
+tuple2To3b :: (a, b) -> x -> (a, x, b)
+tuple2To3b (a, b) x = (a, x, b)
+
+tuple2To3c :: (a, b) -> x -> (a, b, x)
+tuple2To3c (a, b) x = (a, b, x)
diff --git a/src/main/Tuple3.hs b/src/main/Tuple3.hs
new file mode 100644
--- /dev/null
+++ b/src/main/Tuple3.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+module Tuple3(mapFst3, mapSnd3, mapThd3, mapAll3, mapEach3, mapFstF3, mapSndF3, mapThdF3, tuple3To4a, tuple3To4b, tuple3To4c, tuple3To4d, curry3, uncurry3, fst3, snd3, thd3) where
+
+import External
+
+(<&>) :: Functor f => f a -> (a -> b) -> f b
+(<&>) = flip fmap
+
+mapFst3 :: (a -> x) -> (a, b, c) -> (x, b, c)
+mapFst3 f (a, b, c) = (f a, b, c)
+
+mapSnd3 :: (b -> x) -> (a, b, c) -> (a, x, c)
+mapSnd3 f (a, b, c) = (a, f b, c)
+
+mapThd3 :: (c -> x) -> (a, b, c) -> (a, b, x)
+mapThd3 f (a, b, c) = (a, b, f c)
+
+mapAll3 :: (a -> x) -> (a, a, a) -> (x, x, x)
+mapAll3 f (a, b, c) = (f a, f b, f c)
+
+mapEach3 :: (a -> x) -> (b -> y) -> (c -> z) -> (a, b, c) -> (x, y, z)
+mapEach3 f g h (a, b, c) = (f a, g b, h c)
+
+mapFstF3 :: Functor f => (a -> f x) -> (a, b, c) -> f (x, b, c)
+mapFstF3 f (a, b, c) = (f a) <&> (\x -> (x, b, c))
+
+mapSndF3 :: Functor f => (b -> f x) -> (a, b, c) -> f (a, x, c)
+mapSndF3 f (a, b, c) = (f b) <&> (\x -> (a, x, c))
+
+mapThdF3 :: Functor f => (c -> f x) -> (a, b, c) -> f (a, b, x)
+mapThdF3 f (a, b, c) = (f c) <&> (\x -> (a, b, x))
+
+tuple3To4a :: (a, b, c) -> x -> (x, a, b, c)
+tuple3To4a (a, b, c) x = (x, a, b, c)
+
+tuple3To4b :: (a, b, c) -> x -> (a, x, b, c)
+tuple3To4b (a, b, c) x = (a, x, b, c)
+
+tuple3To4c :: (a, b, c) -> x -> (a, b, x, c)
+tuple3To4c (a, b, c) x = (a, b, x, c)
+
+tuple3To4d :: (a, b, c) -> x -> (a, b, c, x)
+tuple3To4d (a, b, c) x = (a, b, c, x)
+
+curry3 :: ((a, b, c) -> x) -> a -> b -> c -> x
+curry3 f a b c = f (a, b, c)
+
+uncurry3 :: (a -> b -> c -> x) -> ((a, b, c) -> x)
+uncurry3 f (a, b, c) = f a b c
+
+fst3 :: (a, b, c) -> a
+fst3 (a, _, _) = a
+
+snd3 :: (a, b, c) -> b
+snd3 (_, b, _) = b
+
+thd3 :: (a, b, c) -> c
+thd3 (_, _, c) = c
diff --git a/src/main/Tuple4.hs b/src/main/Tuple4.hs
new file mode 100644
--- /dev/null
+++ b/src/main/Tuple4.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+module Tuple4(mapFst4, mapSnd4, mapThd4, mapFrt4, mapAll4, mapEach4, mapFstF4, mapSndF4, mapThdF4, mapFrtF4, tuple4To5a, tuple4To5b, tuple4To5c, tuple4To5d, tuple4To5e, curry4, uncurry4, fst4, snd4, thd4, frt4) where
+
+import External
+
+(<&>) :: Functor f => f a -> (a -> b) -> f b
+(<&>) = flip fmap
+
+mapFst4 :: (a -> x) -> (a, b, c, d) -> (x, b, c, d)
+mapFst4 f (a, b, c, d) = (f a, b, c, d)
+
+mapSnd4 :: (b -> x) -> (a, b, c, d) -> (a, x, c, d)
+mapSnd4 f (a, b, c, d) = (a, f b, c, d)
+
+mapThd4 :: (c -> x) -> (a, b, c, d) -> (a, b, x, d)
+mapThd4 f (a, b, c, d) = (a, b, f c, d)
+
+mapFrt4 :: (d -> x) -> (a, b, c, d) -> (a, b, c, x)
+mapFrt4 f (a, b, c, d) = (a, b, c, f d)
+
+mapAll4 :: (a -> x) -> (a, a, a, a) -> (x, x, x, x)
+mapAll4 f (a, b, c, d) = (f a, f b, f c, f d)
+
+mapEach4 :: (a -> x) -> (b -> y) -> (c -> z) -> (d -> l) -> (a, b, c, d) -> (x, y, z, l)
+mapEach4 f g h i (a, b, c, d) = (f a, g b, h c, i d)
+
+mapFstF4 :: Functor f => (a -> f x) -> (a, b, c, d) -> f (x, b, c, d)
+mapFstF4 f (a, b, c, d) = (f a) <&> (\x -> (x, b, c, d))
+
+mapSndF4 :: Functor f => (b -> f x) -> (a, b, c, d) -> f (a, x, c, d)
+mapSndF4 f (a, b, c, d) = (f b) <&> (\x -> (a, x, c, d))
+
+mapThdF4 :: Functor f => (c -> f x) -> (a, b, c, d) -> f (a, b, x, d)
+mapThdF4 f (a, b, c, d) = (f c) <&> (\x -> (a, b, x, d))
+
+mapFrtF4 :: Functor f => (d -> f x) -> (a, b, c, d) -> f (a, b, c, x)
+mapFrtF4 f (a, b, c, d) = (f d) <&> (\x -> (a, b, c, x))
+
+tuple4To5a :: (a, b, c, d) -> x -> (x, a, b, c, d)
+tuple4To5a (a, b, c, d) x = (x, a, b, c, d)
+
+tuple4To5b :: (a, b, c, d) -> x -> (a, x, b, c, d)
+tuple4To5b (a, b, c, d) x = (a, x, b, c, d)
+
+tuple4To5c :: (a, b, c, d) -> x -> (a, b, x, c, d)
+tuple4To5c (a, b, c, d) x = (a, b, x, c, d)
+
+tuple4To5d :: (a, b, c, d) -> x -> (a, b, c, x, d)
+tuple4To5d (a, b, c, d) x = (a, b, c, x, d)
+
+tuple4To5e :: (a, b, c, d) -> x -> (a, b, c, d, x)
+tuple4To5e (a, b, c, d) x = (a, b, c, d, x)
+
+curry4 :: ((a, b, c, d) -> x) -> a -> b -> c -> d -> x
+curry4 f a b c d = f (a, b, c, d)
+
+uncurry4 :: (a -> b -> c -> d -> x) -> ((a, b, c, d) -> x)
+uncurry4 f (a, b, c, d) = f a b c d
+
+fst4 :: (a, b, c, d) -> a
+fst4 (a, _, _, _) = a
+
+snd4 :: (a, b, c, d) -> b
+snd4 (_, b, _, _) = b
+
+thd4 :: (a, b, c, d) -> c
+thd4 (_, _, c, _) = c
+
+frt4 :: (a, b, c, d) -> d
+frt4 (_, _, _, d) = d
