diff --git a/Data/FilePath.hs b/Data/FilePath.hs
--- a/Data/FilePath.hs
+++ b/Data/FilePath.hs
@@ -2,17 +2,24 @@
 module Data.FilePath
     (   Path(..)
     ,   From(..)
+    ,   PathSegment
+    ,   segString
+    ,   mkPathSegment
     ,   FilePath
     ,   (</>)
     ,   rootPath
     ,   relativePath
     ,   mkDirPath
+    ,   mkDirPathSeg
     ,   mkFilePath
+    ,   mkFilePathSeg
     ,   mkRootFilePathBase
     ,   mkFullFilePath
     ,   dirname
     ,   basename
+    ,   basenameSeg
     ,   showp
+    ,   segQ
     ,   dirpathQ
     ,   filepathQ
     ) where
@@ -22,17 +29,49 @@
 import Data.Char
 import Data.List.Split
 import Data.Maybe (fromJust)
+import Data.Semigroup ( Semigroup(..) )
 import Language.Haskell.TH
 import Language.Haskell.TH.Quote
 import GHC.Types
 
+-- | A PathSegment is any single element of a path...i.e. the stuff between
+-- two \'\/\' characters.  Valid path segments cannot contain \'\/\' or control
+-- characters.  PathSegments are also monoids to allow mappending with
+-- prefixes/suffixes.
+newtype PathSegment = PathSegment { _segString :: String }
+  deriving (Eq,Show,Typeable,Data)
+
+instance Semigroup PathSegment where
+  (PathSegment a) <> (PathSegment b) = PathSegment $ a <> b
+
+-- For the motivation behind taking the time and characters to write `segString` instead of just exporting `_segString` pls see <https://github.com/maxpow4h/data-filepath/pull/6>
+
+-- |
+-- Every `PathSegment` is a valid string
+--
+segString :: PathSegment -> String
+segString = _segString
+
+-- | Smart constructor for valid PathSegments.  Valid path segments cannot
+-- contain front slashes or control characters.
+-- This function performs __all__ the checks up front.
+--
+-- * Is the string non-empty?
+-- * Does the string contain forward slashes or control characters?
+--
+mkPathSegment :: String -> Maybe PathSegment
+mkPathSegment s
+    | any (\x -> x == '/' || isControl x) s = Nothing
+    | null s                                = Nothing
+    | otherwise                             = Just $ PathSegment s
+
 data Path = File | Directory
 data From = Root | Relative
 data FilePath (a :: From) (b :: Path) where
   RootPath      :: FilePath Root Directory
   RelativePath  :: FilePath Relative Directory
-  FilePath      :: FilePath a Directory -> String -> FilePath a File
-  DirectoryPath :: FilePath a Directory -> String -> FilePath a Directory
+  FilePath      :: FilePath a Directory -> PathSegment -> FilePath a File
+  DirectoryPath :: FilePath a Directory -> PathSegment -> FilePath a Directory
 
 
 -- Path API
@@ -48,12 +87,26 @@
 p </> (DirectoryPath u s) = DirectoryPath (p </> u) s
 p </> (FilePath u s) = FilePath (p </> u) s
 
+-- | Smart constructor for directories.  Valid directories must be valid
+-- PathSegments and also cannot be empty strings.
 mkDirPath :: String -> Maybe (FilePath Relative Directory)
-mkDirPath s = DirectoryPath RelativePath `fmap` mkf s
+mkDirPath = fmap mkDirPathSeg . mkPathSegment
 
+-- | This function basically defines what the `PathSegment` type is semantically.
+-- It is string like thing which you can safely create a path from.
+-- See `mkPathSegment`, `mkFilePathSeg`
+--
+mkDirPathSeg :: PathSegment -> FilePath Relative Directory
+mkDirPathSeg = DirectoryPath relativePath
+
+-- | Smart constructor for files.  Valid files must be valid PathSegments and
+-- also cannot be empty strings.
 mkFilePath :: String -> Maybe (FilePath Relative File)
-mkFilePath s = FilePath RelativePath `fmap` mkf s
+mkFilePath = fmap mkFilePathSeg .  mkPathSegment
 
+mkFilePathSeg :: PathSegment -> FilePath Relative File
+mkFilePathSeg = FilePath relativePath
+
 mkRootFilePathBase :: String -> Maybe (FilePath Root Directory)
 mkRootFilePathBase ('/':s) = do
   ys <- xs
@@ -79,33 +132,38 @@
 dirname (FilePath dir _) = dir
 
 basename :: FilePath a File -> String
-basename (FilePath _ bname) = bname
+basename (FilePath _ (PathSegment bname)) = bname
 
+basenameSeg :: FilePath a File -> PathSegment
+basenameSeg (FilePath _ bname) = bname
+
 showp :: FilePath a b -> String
 showp RootPath = ""
 showp RelativePath = "."
-showp (DirectoryPath u s) = showp u ++ "/" ++ s
-showp (FilePath u s) = showp u ++ "/" ++ s
+showp (DirectoryPath u (PathSegment s)) = showp u ++ "/" ++ s
+showp (FilePath u (PathSegment s)) = showp u ++ "/" ++ s
 
-mkf :: String -> Maybe String
-mkf "" = Nothing -- an empty string is an invalid file/dir name
-mkf s = if any (\x -> x == '/' || isControl x) s
-  then Nothing
-  else Just s
+-- TODO: could it split the delimiters?
+segQ :: QuasiQuoter
+segQ = QuasiQuoter qExp qPat (error "path segments are not types") (error "path segments are not decs")
+  where
+    qExp :: String -> ExpQ
+    qExp s = dataToExpQ (const Nothing) (fromJust (mkPathSegment s) :: PathSegment)
+    qPat = undefined
 
 -- TODO: could it split the delimiters?
 dirpathQ :: QuasiQuoter
 dirpathQ = QuasiQuoter qExp qPat (error "dir paths are not types") (error "dir paths are not decs")
   where
     qExp :: String -> ExpQ
-    qExp s = dataToExpQ (const Nothing) (DirectoryPath RelativePath (fromJust (mkf s)) :: FilePath Relative Directory)
+    qExp s = dataToExpQ (const Nothing) (fromJust (mkDirPath s) :: FilePath Relative Directory)
     qPat = undefined
 
 filepathQ :: QuasiQuoter
 filepathQ = QuasiQuoter qExp qPat (error "file paths are not types") (error "file paths are not decs")
   where
     qExp :: String -> ExpQ
-    qExp s = dataToExpQ (const Nothing) (FilePath RelativePath (fromJust (mkf s)) :: FilePath Relative File)
+    qExp s = dataToExpQ (const Nothing) (fromJust (mkFilePath s) :: FilePath Relative File)
     qPat = undefined
 
 -- data / typeable
diff --git a/data-filepath.cabal b/data-filepath.cabal
--- a/data-filepath.cabal
+++ b/data-filepath.cabal
@@ -1,5 +1,5 @@
 name:                data-filepath
-version:             2.1.0.1
+version:             2.1.1.0
 synopsis:            A type safe file path data structure
 description:         A type safe file path data structure
 license:             BSD3
@@ -19,7 +19,12 @@
     location:           https://github.com/maxpow4h/data-filepath.git
 
 library
-  exposed-modules:     Data.FilePath
-  other-extensions:    CPP, GADTs, DataKinds, KindSignatures, StandaloneDeriving, RankNTypes, DeriveDataTypeable, FlexibleInstances, MagicHash
-  build-depends:       base >=4.6 && <4.9, split >=0.2 && <0.3, template-haskell, ghc-prim
+  exposed-modules:      Data.FilePath
+  other-extensions:     CPP, GADTs, DataKinds, KindSignatures, StandaloneDeriving, RankNTypes, DeriveDataTypeable, FlexibleInstances, MagicHash
+  build-depends:        base                >= 4.6 && < 4.9
+                    ,   semigroups          == 0.16.*
+                    ,   split               >= 0.2 && < 0.3
+                    ,   template-haskell
+                    ,   ghc-prim
+
   default-language:    Haskell2010
