diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,8 @@
+0.5.2
+
+* Add `ReadFilePathsT` to read a list of `FilePath`
+* Add `joinPath` value
+
 0.5.1
 
 * Fix bug in `Find` module
diff --git a/filepather.cabal b/filepather.cabal
--- a/filepather.cabal
+++ b/filepather.cabal
@@ -1,5 +1,5 @@
 name:                 filepather
-version:              0.5.1
+version:              0.5.2
 synopsis:             Functions on System.FilePath
 description:
   Functions over @System.FilePath@ including a find function for recursing down directories.
@@ -29,6 +29,7 @@
                       System.FilePath.FilePather.IO
                       System.FilePath.FilePather.Posix
                       System.FilePath.FilePather.ReadFilePath
+                      System.FilePath.FilePather.ReadFilePaths
 
   build-depends:         base                 >= 4.15 && < 6
                        , bytestring           >= 0.11.2.0 && < 0.12
diff --git a/src/System/FilePath/FilePather.hs b/src/System/FilePath/FilePather.hs
--- a/src/System/FilePath/FilePather.hs
+++ b/src/System/FilePath/FilePather.hs
@@ -8,3 +8,4 @@
 import System.FilePath.FilePather.IO as P
 import System.FilePath.FilePather.Posix as P
 import System.FilePath.FilePather.ReadFilePath as P
+import System.FilePath.FilePather.ReadFilePaths as P
diff --git a/src/System/FilePath/FilePather/Posix.hs b/src/System/FilePath/FilePather/Posix.hs
--- a/src/System/FilePath/FilePather/Posix.hs
+++ b/src/System/FilePath/FilePather/Posix.hs
@@ -24,6 +24,7 @@
 , replaceDirectory
 , combine
 , splitPath
+, joinPath
 , splitDirectories
 , splitDrive
 , joinDrive
@@ -50,9 +51,11 @@
 import Data.Bool( Bool )
 import Data.Maybe ( Maybe )
 import qualified System.FilePath.Posix as FP
-import System.FilePath.Posix as SFP(FilePath)
+import System.FilePath.Posix as SFP( FilePath )
 import System.FilePath.FilePather.ReadFilePath
     ( ReadFilePathT, liftReadFilePath )
+import System.FilePath.FilePather.ReadFilePaths
+    ( ReadFilePathsT, liftReadFilePaths )
 
 splitExtension ::
   Applicative f =>
@@ -216,6 +219,13 @@
 splitPath =
   liftReadFilePath FP.splitPath
 {-# INLINE splitPath #-}
+
+joinPath ::
+  Applicative f =>
+  ReadFilePathsT e f FilePath
+joinPath =
+  liftReadFilePaths FP.joinPath
+{-# INLINE joinPath #-}
 
 splitDirectories ::
   Applicative f =>
diff --git a/src/System/FilePath/FilePather/ReadFilePath.hs b/src/System/FilePath/FilePather/ReadFilePath.hs
--- a/src/System/FilePath/FilePather/ReadFilePath.hs
+++ b/src/System/FilePath/FilePather/ReadFilePath.hs
@@ -6,7 +6,7 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 
 module System.FilePath.FilePather.ReadFilePath(
-  ReadFilePathT
+  ReadFilePathT(..)
 , ReadFilePathT1
 , ReadFilePath1
 , readFilePath
diff --git a/src/System/FilePath/FilePather/ReadFilePaths.hs b/src/System/FilePath/FilePather/ReadFilePaths.hs
new file mode 100644
--- /dev/null
+++ b/src/System/FilePath/FilePather/ReadFilePaths.hs
@@ -0,0 +1,294 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module System.FilePath.FilePather.ReadFilePaths (
+  ReadFilePathsT
+, ReadFilePathsT1
+, ReadFilePaths1
+, readFilePaths1
+, readFilePaths
+, swapReadFilePaths
+, pureReadFilePaths
+, liftReadFilePaths
+, successReadFilePaths
+, errorReadFilePaths
+, maybeReadFilePaths
+, tryReadFilePaths
+) where
+
+import Control.Applicative ( Applicative((<*>), pure) )
+import Control.Category ( Category((.)) )
+import Control.Exception ( try, Exception )
+import Control.Lens
+    ( view,
+      iso,
+      swapped,
+      _Wrapped,
+      Field1(_1),
+      Iso,
+      Rewrapped,
+      Wrapped(..) )
+import Control.Monad
+    ( join, Monad(return, (>>=)) )
+import Control.Monad.Cont.Class ( MonadCont(callCC) )
+import Control.Monad.Error.Class ( MonadError(throwError, catchError) )
+import Control.Monad.Fail ( MonadFail(fail) )
+import Control.Monad.Fix ( MonadFix(mfix) )
+import Control.Monad.IO.Class ( MonadIO(liftIO) )
+import Control.Monad.Morph ( MFunctor(hoist), MMonad(embed) )
+import Control.Monad.Reader.Class ( MonadReader(reader, local, ask) )
+import Control.Monad.State.Class ( MonadState(state, get, put) )
+import Control.Monad.Trans.Class(MonadTrans(lift))
+import Control.Monad.Writer.Class ( MonadWriter(pass, tell, writer, listen) )
+import Control.Monad.Zip ( MonadZip(mzipWith) )
+import Data.Either ( Either(..), either )
+import Data.Functor ( Functor(fmap) )
+import Data.Functor.Alt ( Apply((<.>)), Alt((<!>)) )
+import Data.Functor.Bind ( Bind((>>-)) )
+import Data.Functor.Identity( Identity(..) )
+import Data.Maybe ( Maybe, maybe )
+import Data.Monoid ( Monoid(mempty, mappend) )
+import Data.Semigroup ( Semigroup((<>)) )
+import System.FilePath ( FilePath )
+import System.FilePath.FilePather.ReadFilePath
+    ( ReadFilePathT(..) )
+import System.IO ( IO )
+
+newtype ReadFilePathsT e f a =
+  ReadFilePathsT ([FilePath] -> f (Either e a))
+
+instance ReadFilePathsT e f a ~ t =>
+  Rewrapped (ReadFilePathsT e' f' a') t
+
+instance Wrapped (ReadFilePathsT e f a) where
+  type Unwrapped (ReadFilePathsT e f a) =
+    [FilePath]
+    -> f (Either e a)
+  _Wrapped' =
+    iso (\(ReadFilePathsT x) -> x) ReadFilePathsT
+  {-# INLINE _Wrapped' #-}
+
+type ReadFilePaths e a =
+  ReadFilePathsT e Identity a
+
+type ReadFilePathsT1 e f =
+  ReadFilePathsT e f ()
+
+type ReadFilePaths1 e f =
+  ReadFilePaths e ()
+
+readFilePaths1 ::
+  ReadFilePathsT e f a
+  -> ReadFilePathT e f a
+readFilePaths1 x =
+  ReadFilePathT (view _Wrapped x . pure)
+{-# INLINE readFilePaths1 #-}
+
+readFilePaths ::
+  Iso
+    (ReadFilePaths e a)
+    (ReadFilePaths e' a')
+    ([FilePath] -> Either e a)
+    ([FilePath] -> Either e' a')
+readFilePaths =
+  iso
+    (\(ReadFilePathsT x) -> runIdentity . x)
+    (\p -> ReadFilePathsT (Identity . p))
+{-# INLINE readFilePaths #-}
+
+swapReadFilePaths ::
+  Functor f =>
+  Iso
+    (ReadFilePathsT e f a)
+    (ReadFilePathsT e' f a')
+    (ReadFilePathsT a f e)
+    (ReadFilePathsT a' f e')
+swapReadFilePaths =
+  iso
+    (\r -> ReadFilePathsT (fmap (view swapped) . view _Wrapped r))
+    (\r -> ReadFilePathsT (fmap (view swapped) . view _Wrapped r))
+{-# INLINE swapReadFilePaths #-}
+
+pureReadFilePaths ::
+  Applicative f =>
+  ReadFilePaths e a
+  -> ReadFilePathsT e f a
+pureReadFilePaths =
+  hoist (pure . runIdentity)
+{-# INLINE pureReadFilePaths #-}
+
+liftReadFilePaths ::
+  Applicative f =>
+  ([FilePath] -> a)
+  -> ReadFilePathsT e f a
+liftReadFilePaths =
+  pureReadFilePaths . reader
+{-# INLINE liftReadFilePaths #-}
+
+successReadFilePaths ::
+  Functor f =>
+  ([FilePath] -> f a)
+  -> ReadFilePathsT e f a
+successReadFilePaths k =
+  ReadFilePathsT (fmap Right . k)
+{-# INLINE successReadFilePaths #-}
+
+errorReadFilePaths ::
+  Functor f =>
+  ([FilePath] -> f e)
+  -> ReadFilePathsT e f a
+errorReadFilePaths k =
+  ReadFilePathsT (fmap Left . k)
+{-# INLINE errorReadFilePaths #-}
+
+maybeReadFilePaths ::
+  Functor f =>
+  ([FilePath] -> f (Maybe a))
+  -> ReadFilePathsT () f a
+maybeReadFilePaths k =
+  ReadFilePathsT (fmap (maybe (Left ()) Right) . k)
+{-# INLINE maybeReadFilePaths #-}
+
+tryReadFilePaths ::
+  Exception e =>
+  ([FilePath] -> IO a)
+  -> ReadFilePathsT e IO a
+tryReadFilePaths k =
+  ReadFilePathsT (try . k)
+{-# INLINE tryReadFilePaths #-}
+
+instance (Monad f, Semigroup a) => Semigroup (ReadFilePathsT e f a) where
+  ReadFilePathsT x <> ReadFilePathsT y =
+    ReadFilePathsT (\p -> x p >>= either (pure . Left) (\a -> fmap (fmap (a <>)) (y p)))
+  {-# INLINE (<>) #-}
+
+instance (Monad f, Monoid a) => Monoid (ReadFilePathsT e f a) where
+  mappend =
+    (<>)
+  {-# INLINE mappend #-}
+  mempty =
+    ReadFilePathsT (pure (pure (pure mempty)))
+  {-# INLINE mempty #-}
+
+instance Functor f => Functor (ReadFilePathsT e f) where
+  fmap f (ReadFilePathsT x) =
+    ReadFilePathsT (fmap (fmap (fmap f)) x)
+  {-# INLINE fmap #-}
+
+instance Monad f => Apply (ReadFilePathsT e f) where
+  ReadFilePathsT f <.> ReadFilePathsT k =
+    ReadFilePathsT (\p -> f p >>= either (pure . Left) (\a -> fmap (fmap a) (k p)))
+  {-# INLINE (<.>) #-}
+
+instance Monad f => Bind (ReadFilePathsT e f) where
+  ReadFilePathsT f >>- g =
+    ReadFilePathsT (\p -> f p >>= either (pure . Left) (\a -> view _Wrapped (g a) p))
+  {-# INLINE (>>-) #-}
+
+instance Monad f => Applicative (ReadFilePathsT e f) where
+  (<*>) =
+    (<.>)
+  pure =
+    ReadFilePathsT . pure . pure . pure
+
+instance Monad f => Alt (ReadFilePathsT e f) where
+  ReadFilePathsT a <!> ReadFilePathsT b =
+    ReadFilePathsT (\p -> a p >>= either (pure (b p)) (pure . pure))
+  {-# INLINE (<!>) #-}
+
+instance Monad f => Monad (ReadFilePathsT e f) where
+  (>>=) =
+    (>>-)
+  {-# INLINE (>>=) #-}
+  return =
+    pure
+  {-# INLINE return #-}
+
+instance MonadTrans (ReadFilePathsT e) where
+  lift =
+    ReadFilePathsT . pure . fmap pure
+  {-# INLINE lift #-}
+
+instance MonadIO f => MonadIO (ReadFilePathsT e f) where
+  liftIO =
+    ReadFilePathsT . pure . liftIO . fmap pure
+  {-# INLINE liftIO #-}
+
+instance MFunctor (ReadFilePathsT e) where
+  hoist k (ReadFilePathsT f) =
+    ReadFilePathsT (k .f)
+  {-# INLINE hoist #-}
+
+instance MMonad (ReadFilePathsT e) where
+  embed k (ReadFilePathsT f) =
+    ReadFilePathsT (\p -> fmap join (view _Wrapped (k (f p)) p))
+  {-# INLINE embed #-}
+
+instance Monad f => MonadReader [FilePath] (ReadFilePathsT e f) where
+  ask =
+    ReadFilePathsT (pure . pure)
+  {-# INLINE ask #-}
+  local k (ReadFilePathsT f) =
+    ReadFilePathsT (f . k)
+  {-# INLINE local #-}
+  reader k =
+    ReadFilePathsT (pure . pure . k)
+  {-# INLINE reader #-}
+
+instance MonadState [FilePath] f => MonadState [FilePath] (ReadFilePathsT e f) where
+  state =
+    lift . state
+  {-# INLINE state #-}
+  get =
+    lift get
+  {-# INLINE get #-}
+  put =
+    lift . put
+  {-# INLINE put #-}
+
+instance MonadWriter [FilePath] f => MonadWriter [FilePath] (ReadFilePathsT e f) where
+  writer =
+    lift . writer
+  {-# INLINE writer #-}
+  tell =
+    lift . tell
+  {-# INLINE tell #-}
+  listen (ReadFilePathsT f) =
+    ReadFilePathsT (\p -> fmap (fmap (\a -> (a, p))) (f p))
+  {-# INLINE listen #-}
+  pass (ReadFilePathsT f) =
+    ReadFilePathsT (fmap (fmap (view _1)) . f)
+  {-# INLINE pass #-}
+
+instance MonadFail f => MonadFail (ReadFilePathsT e f) where
+  fail =
+    lift . fail
+  {-# INLINE fail #-}
+
+instance MonadFix f => MonadFix (ReadFilePathsT e f) where
+  mfix f =
+    ReadFilePathsT (\p -> mfix (either (pure . Left) (\a -> view _Wrapped (f a) p)))
+  {-# INLINE mfix #-}
+
+instance MonadZip f => MonadZip (ReadFilePathsT e f) where
+  mzipWith f (ReadFilePathsT m) (ReadFilePathsT n) =
+    ReadFilePathsT (\p -> m p >>= either (pure . Left) (\a -> fmap (fmap (f a)) (n p)))
+  {-# INLINE mzipWith #-}
+
+instance MonadCont f => MonadCont (ReadFilePathsT e f) where
+  callCC p =
+    ReadFilePathsT (\r -> callCC (\c -> view _Wrapped (p (ReadFilePathsT . pure . c . pure)) r))
+  {-# INLINE callCC #-}
+
+instance MonadError e f => MonadError e (ReadFilePathsT e f) where
+  throwError =
+    lift . throwError
+  {-# INLINE throwError #-}
+  catchError (ReadFilePathsT f) g =
+    ReadFilePathsT (\ r -> catchError (f r) (\ e -> view _Wrapped (g e) r))
+  {-# INLINE catchError #-}
+
