diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+0.11.0
+	* Many API breaking changes
+	* Remove RelC and Fn, because they complicate API/break semantics (see #29)
+	* Redo 'parseAny'
+	* Unexpose HPath.Internal
+	* Don't preserve trailing path separators (if you need to pass something to a C function that way, do it manually)
+	* Added `rooPath`, `isRootPath`, `getAllComponents`, `getAllComponentsAfterRoot`
 0.10.2
 	* Add `parseAny` and the related QuasiQuoter
 0.10.1
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -28,11 +28,9 @@
 ## Differences to 'path'
 
 * doesn't attempt to fake IO-related information into the path, so whether a path points to a file or directory is up to your IO-code to decide...
-* trailing path separators will be preserved if they exist, no messing with that
 * uses safe ByteString for filepaths under the hood instead of unsafe String
 * fixes broken [dirname](https://github.com/chrisdone/path/issues/18)
 * renames dirname/filename to basename/dirname to match the POSIX shell functions
-* introduces a new `Path Fn` for safe filename guarantees and a `RelC` class
 * allows pattern matching via unidirectional PatternSynonym
 * uses simple doctest for testing
 * allows `~/` as relative path, because on posix level `~` is just a regular filename that does _NOT_ point to `$HOME`
diff --git a/hpath.cabal b/hpath.cabal
--- a/hpath.cabal
+++ b/hpath.cabal
@@ -1,5 +1,5 @@
 name:                hpath
-version:             0.10.2
+version:             0.11.0
 synopsis:            Support for well-typed paths
 description:         Support for well-typed paths, utilizing ByteString under the hood.
 license:             BSD3
@@ -30,7 +30,7 @@
   else
     ghc-options:       -Wall
   exposed-modules:   HPath
-                     HPath.Internal
+  other-modules:     HPath.Internal
   build-depends:     base >= 4.8 && <5
                    , bytestring >= 0.10.0.0
                    , deepseq
diff --git a/src/HPath.hs b/src/HPath.hs
--- a/src/HPath.hs
+++ b/src/HPath.hs
@@ -25,39 +25,39 @@
    Abs
   ,Path
   ,Rel
-  ,Fn
   ,PathParseException
   ,PathException
-  ,RelC
 #if __GLASGOW_HASKELL__ >= 708
   -- * PatternSynonyms/ViewPatterns
   ,pattern Path
 #endif
-   -- * Path Parsing
+   -- * Path Construction
   ,parseAbs
-  ,parseFn
   ,parseRel
   ,parseAny
+  ,rootPath
   -- * Path Conversion
   ,fromAbs
   ,fromRel
   ,toFilePath
+  ,fromAny
   -- * Path Operations
   ,(</>)
   ,basename
   ,dirname
-  ,isParentOf
   ,getAllParents
+  ,getAllComponents
+  ,getAllComponentsAfterRoot
   ,stripDir
+  -- * Path Examination
+  ,isParentOf
+  ,isRootPath
   -- * Path IO helpers
   ,withAbsPath
   ,withRelPath
-  ,withFnPath
   -- * Quasiquoters
   ,abs
   ,rel
-  ,fn
-  ,any
   )
   where
 
@@ -91,14 +91,10 @@
 -- | A relative path; one without a root.
 data Rel deriving (Typeable)
 
--- | A filename, without any '/'.
-data Fn deriving (Typeable)
-
 -- | Exception when parsing a location.
 data PathParseException
   = InvalidAbs ByteString
   | InvalidRel ByteString
-  | InvalidFn ByteString
   | Couldn'tStripPrefixTPS ByteString ByteString
   deriving (Show,Typeable)
 instance Exception PathParseException
@@ -107,11 +103,7 @@
   deriving (Show,Typeable)
 instance Exception PathException
 
-class RelC m
 
-instance RelC Rel
-instance RelC Fn
-
 --------------------------------------------------------------------------------
 -- PatternSynonyms
 
@@ -138,7 +130,7 @@
 -- >>> parseAbs "/abc/def"      :: Maybe (Path Abs)
 -- Just "/abc/def"
 -- >>> parseAbs "/abc/def/.///" :: Maybe (Path Abs)
--- Just "/abc/def/"
+-- Just "/abc/def"
 -- >>> parseAbs "abc"           :: Maybe (Path Abs)
 -- Nothing
 -- >>> parseAbs ""              :: Maybe (Path Abs)
@@ -151,7 +143,7 @@
   if isAbsolute filepath &&
      isValid filepath &&
      not (hasParentDir filepath)
-     then return (MkPath $ normalise filepath)
+     then return (MkPath . dropTrailingPathSeparator . normalise $ filepath)
      else throwM (InvalidAbs filepath)
 
 
@@ -166,11 +158,11 @@
 -- >>> parseRel "abc"        :: Maybe (Path Rel)
 -- Just "abc"
 -- >>> parseRel "def/"       :: Maybe (Path Rel)
--- Just "def/"
+-- Just "def"
 -- >>> parseRel "abc/def"    :: Maybe (Path Rel)
 -- Just "abc/def"
 -- >>> parseRel "abc/def/."  :: Maybe (Path Rel)
--- Just "abc/def/"
+-- Just "abc/def"
 -- >>> parseRel "/abc"       :: Maybe (Path Rel)
 -- Nothing
 -- >>> parseRel ""           :: Maybe (Path Rel)
@@ -189,46 +181,11 @@
      filepath /= BS.pack [_period, _period] &&
      not (hasParentDir filepath) &&
      isValid filepath
-     then return (MkPath $ normalise filepath)
+     then return (MkPath . dropTrailingPathSeparator . normalise $ filepath)
      else throwM (InvalidRel filepath)
 
 
--- | Parses a filename. Filenames must not contain slashes.
--- Excludes '.' and '..'.
---
--- Throws: 'PathParseException'
---
--- >>> parseFn "abc"        :: Maybe (Path Fn)
--- Just "abc"
--- >>> parseFn "..."        :: Maybe (Path Fn)
--- Just "..."
--- >>> parseFn "def/"       :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn "abc/def"    :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn "abc/def/."  :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn "/abc"       :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn ""           :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn "abc/../foo" :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn "."          :: Maybe (Path Fn)
--- Nothing
--- >>> parseFn ".."         :: Maybe (Path Fn)
--- Nothing
-parseFn :: MonadThrow m
-        => ByteString -> m (Path Fn)
-parseFn filepath =
-  if isFileName filepath &&
-     filepath /= BS.singleton _period &&
-     filepath /= BS.pack [_period, _period] &&
-     isValid filepath
-     then return (MkPath filepath)
-     else throwM (InvalidFn filepath)
 
-
 -- | Parses a path, whether it's relative or absolute. Will lose
 -- information on whether it's relative or absolute. If you need to know,
 -- reparse it.
@@ -238,32 +195,36 @@
 --
 -- Throws: 'PathParseException'
 --
--- >>> parseAny "/abc"       :: Maybe (Path a)
--- Just "/abc"
--- >>> parseAny "..."        :: Maybe (Path a)
--- Just "..."
--- >>> parseAny "abc/def"    :: Maybe (Path a)
--- Just "abc/def"
--- >>> parseAny "abc/def/."  :: Maybe (Path a)
--- Just "abc/def/"
--- >>> parseAny "/abc"       :: Maybe (Path a)
--- Just "/abc"
--- >>> parseAny ""           :: Maybe (Path a)
+-- >>> parseAny "/abc"       :: Maybe (Either (Path Abs) (Path Rel))
+-- Just (Left "/abc")
+-- >>> parseAny "..."        :: Maybe (Either (Path Abs) (Path Rel))
+-- Just (Right "...")
+-- >>> parseAny "abc/def"    :: Maybe (Either (Path Abs) (Path Rel))
+-- Just (Right "abc/def")
+-- >>> parseAny "abc/def/."  :: Maybe (Either (Path Abs) (Path Rel))
+-- Just (Right "abc/def")
+-- >>> parseAny "/abc"       :: Maybe (Either (Path Abs) (Path Rel))
+-- Just (Left "/abc")
+-- >>> parseAny ""           :: Maybe (Either (Path Abs) (Path Rel))
 -- Nothing
--- >>> parseAny "abc/../foo" :: Maybe (Path a)
+-- >>> parseAny "abc/../foo" :: Maybe (Either (Path Abs) (Path Rel))
 -- Nothing
--- >>> parseAny "."          :: Maybe (Path a)
+-- >>> parseAny "."          :: Maybe (Either (Path Abs) (Path Rel))
 -- Nothing
--- >>> parseAny ".."         :: Maybe (Path a)
+-- >>> parseAny ".."         :: Maybe (Either (Path Abs) (Path Rel))
 -- Nothing
-parseAny :: MonadThrow m => ByteString -> m (Path a)
+parseAny :: MonadThrow m => ByteString -> m (Either (Path Abs) (Path Rel))
 parseAny filepath = case parseAbs filepath of
-  Just (MkPath p) -> pure $ (MkPath p)
+  Just p -> pure $ Left p
   Nothing         -> case parseRel filepath of
-    Just (MkPath p) -> pure $ (MkPath p)
-    Nothing         -> throwM (InvalidRel filepath)
+    Just p -> pure $ Right p
+    Nothing       -> throwM (InvalidRel filepath)
 
 
+rootPath :: Path Abs
+rootPath = (MkPath (BS.singleton _slash))
+
+
 --------------------------------------------------------------------------------
 -- Path Conversion
 
@@ -276,10 +237,13 @@
 fromAbs = toFilePath
 
 -- | Convert a relative Path to a ByteString type.
-fromRel :: RelC r => Path r -> ByteString
+fromRel :: Path Rel -> ByteString
 fromRel = toFilePath
 
+fromAny :: Either (Path Abs) (Path Rel) -> ByteString
+fromAny = either toFilePath toFilePath
 
+
 --------------------------------------------------------------------------------
 -- Path Operations
 
@@ -298,15 +262,16 @@
 -- "/path/to/file"
 -- >>> (MkPath "/")        </> (MkPath "file/lal" :: Path Rel)
 -- "/file/lal"
--- >>> (MkPath "/")        </> (MkPath "file/"    :: Path Rel)
--- "/file/"
-(</>) :: RelC r => Path b -> Path r -> Path b
+-- >>> (MkPath "/")        </> (MkPath "file"    :: Path Rel)
+-- "/file"
+(</>) :: Path b -> Path Rel -> Path b
 (</>) (MkPath a) (MkPath b) = MkPath (a' `BS.append` b)
   where
-    a' = if BS.last a == pathSeparator
-         then a
-         else addTrailingPathSeparator a
+    a' = if hasTrailingPathSeparator a
+            then a
+            else addTrailingPathSeparator a
 
+
 -- | Strip directory from path, making it relative to that directory.
 -- Throws 'Couldn'tStripPrefixDir' if directory is not a parent of the path.
 --
@@ -333,27 +298,13 @@
   where
     p' = addTrailingPathSeparator p
 
--- | Is p a parent of the given location? Implemented in terms of
--- 'stripDir'. The bases must match.
---
--- >>> (MkPath "/lal/lad")     `isParentOf` (MkPath "/lal/lad/fad")
--- True
--- >>> (MkPath "lal/lad")      `isParentOf` (MkPath "lal/lad/fad")
--- True
--- >>> (MkPath "/")            `isParentOf` (MkPath "/")
--- False
--- >>> (MkPath "/lal/lad/fad") `isParentOf` (MkPath "/lal/lad")
--- False
--- >>> (MkPath "fad")          `isParentOf` (MkPath "fad")
--- False
-isParentOf :: Path b -> Path b -> Bool
-isParentOf p l = isJust (stripDir p l :: Maybe (Path Rel))
 
-
 -- |Get all parents of a path.
 --
 -- >>> getAllParents (MkPath "/abs/def/dod")
 -- ["/abs/def","/abs","/"]
+-- >>> getAllParents (MkPath "/foo")
+-- ["/"]
 -- >>> getAllParents (MkPath "/")
 -- []
 getAllParents :: Path Abs -> [Path Abs]
@@ -361,9 +312,29 @@
   | np == BS.singleton pathSeparator = []
   | otherwise = dirname (MkPath np) : getAllParents (dirname $ MkPath np)
   where
-    np = dropTrailingPathSeparator . normalise $ p
+    np = normalise p
 
 
+-- | Gets all path components.
+--
+-- >>> getAllComponents (MkPath "abs/def/dod")
+-- ["abs","def","dod"]
+-- >>> getAllComponents (MkPath "abs")
+-- ["abs"]
+getAllComponents :: Path Rel -> [Path Rel]
+getAllComponents (MkPath p) = fmap MkPath . splitDirectories $ p
+
+
+-- | Gets all path components after the "/" root directory.
+--
+-- >>> getAllComponentsAfterRoot (MkPath "/abs/def/dod")
+-- ["abs","def","dod"]
+-- >>> getAllComponentsAfterRoot (MkPath "/abs")
+-- ["abs"]
+getAllComponentsAfterRoot :: Path Abs -> [Path Rel]
+getAllComponentsAfterRoot p = getAllComponents (fromJust $ stripDir rootPath p)
+
+
 -- | Extract the directory name of a path.
 --
 -- >>> dirname (MkPath "/abc/def/dod")
@@ -371,7 +342,7 @@
 -- >>> dirname (MkPath "/")
 -- "/"
 dirname :: Path Abs -> Path Abs
-dirname (MkPath fp) = MkPath (takeDirectory $ dropTrailingPathSeparator fp)
+dirname (MkPath fp) = MkPath (takeDirectory fp)
 
 -- | Extract the file part of a path.
 --
@@ -382,21 +353,54 @@
 --
 -- Throws: `PathException` if given the root path "/"
 --
--- >>> basename (MkPath "/abc/def/dod") :: Maybe (Path Fn)
+-- >>> basename (MkPath "/abc/def/dod") :: Maybe (Path Rel)
 -- Just "dod"
--- >>> basename (MkPath "/abc/def/dod/") :: Maybe (Path Fn)
+-- >>> basename (MkPath "abc/def/dod")  :: Maybe (Path Rel)
 -- Just "dod"
--- >>> basename (MkPath "/")            :: Maybe (Path Fn)
+-- >>> basename (MkPath "dod")          :: Maybe (Path Rel)
+-- Just "dod"
+-- >>> basename (MkPath "/")            :: Maybe (Path Rel)
 -- Nothing
-basename :: MonadThrow m => Path b -> m (Path Fn)
+basename :: MonadThrow m => Path b -> m (Path Rel)
 basename (MkPath l)
   | not (isAbsolute rl) = return $ MkPath rl
   | otherwise           = throwM RootDirHasNoBasename
   where
-    rl = last . splitPath . dropTrailingPathSeparator $ l
+    rl = last . splitPath $ l
 
 
+
 --------------------------------------------------------------------------------
+-- Path Examination
+
+-- | Is p a parent of the given location? Implemented in terms of
+-- 'stripDir'. The bases must match.
+--
+-- >>> (MkPath "/lal/lad")     `isParentOf` (MkPath "/lal/lad/fad")
+-- True
+-- >>> (MkPath "lal/lad")      `isParentOf` (MkPath "lal/lad/fad")
+-- True
+-- >>> (MkPath "/")            `isParentOf` (MkPath "/")
+-- False
+-- >>> (MkPath "/lal/lad/fad") `isParentOf` (MkPath "/lal/lad")
+-- False
+-- >>> (MkPath "fad")          `isParentOf` (MkPath "fad")
+-- False
+isParentOf :: Path b -> Path b -> Bool
+isParentOf p l = isJust (stripDir p l :: Maybe (Path Rel))
+
+
+-- | Check whether the given Path is the root "/" path.
+--
+-- >>> isRootPath (MkPath "/lal/lad")
+-- False
+-- >>> isRootPath (MkPath "/")
+-- True
+isRootPath :: Path Abs -> Bool
+isRootPath = (== rootPath)
+
+
+--------------------------------------------------------------------------------
 -- Path IO helpers
 
 
@@ -408,10 +412,7 @@
 withRelPath (MkPath p) action = action p
 
 
-withFnPath :: Path Fn -> (ByteString -> IO a) -> IO a
-withFnPath (MkPath p) action = action p
 
-
 ------------------------
 -- ByteString helpers
 
@@ -447,12 +448,6 @@
 mkRel :: ByteString -> Q Exp
 mkRel = either (error . show) lift . parseRel
 
-mkFN :: ByteString -> Q Exp
-mkFN = either (error . show) lift . parseFn
-
-mkAny :: ByteString -> Q Exp
-mkAny = either (error . show) lift . parseAny
-
 -- | Quasiquote an absolute Path. This accepts Unicode Chars and will encode as UTF-8.
 --
 -- >>> [abs|/etc/profile|] :: Path Abs
@@ -475,23 +470,3 @@
 rel :: QuasiQuoter
 rel = qq mkRel
 
--- | Quasiquote a file name. This accepts Unicode Chars and will encode as UTF-8.
---
--- >>> [fn|etc|] :: Path Fn
--- "etc"
--- >>> [fn||] :: Path Fn
--- "\239\131\144"
-fn :: QuasiQuoter
-fn = qq mkFN
-
--- | Quasiquote any path (relative or absolute).
--- This accepts Unicode Chars and will encode as UTF-8.
---
--- >>> [any|/etc/profile|] :: Path a
--- "/etc/profile"
--- >>> [any|etc|] :: Path a
--- "etc"
--- >>> [any||] :: Path a
--- "\239\131\144"
-any :: QuasiQuoter
-any = qq mkAny
diff --git a/src/HPath/Internal.hs b/src/HPath/Internal.hs
--- a/src/HPath/Internal.hs
+++ b/src/HPath/Internal.hs
@@ -10,15 +10,19 @@
 import Data.ByteString (ByteString)
 import Data.Data
 
--- | Path of some base and type.
+-- | The main Path type.
 --
--- Internally is a ByteString. The ByteString can be of two formats only:
+-- The type variable 'b' is either:
 --
--- 1. without trailing path separator: @file.txt@, @foo\/bar.txt@, @\/foo\/bar.txt@
--- 2. with trailing path separator: @foo\/@, @\/foo\/bar\/@
+--   * Abs -- absolute path
+--   * Rel -- relative path
 --
--- There are no duplicate
--- path separators @\/\/@, no @..@, no @.\/@, no @~\/@, etc.
+-- Internally is a ByteString. The path is guaranteed to
+-- be normalised and contain no trailing Path separators,
+-- except for the '/' root path.
+--
+-- There are no duplicate path separators
+-- @\/\/@, no @..@, no @.\/@, no @~\/@, etc.
 data Path b = MkPath ByteString
   deriving (Typeable)
 
