diff --git a/pathtype.cabal b/pathtype.cabal
--- a/pathtype.cabal
+++ b/pathtype.cabal
@@ -1,5 +1,5 @@
 Name:                pathtype
-Version:             0.5.5
+Version:             0.6
 Synopsis:            Type-safe replacement for System.FilePath etc
 Description:         This package provides type-safe access to filepath manipulations.
 		     .
@@ -73,7 +73,15 @@
 		     The basic API (and properties satisfied) are heavily influenced
 		     by Neil Mitchell's "System.FilePath" module.
                      .
+                     Related packages:
                      .
+                     * @path@: Provides a wrapper type around 'FilePath'
+                       and maps to functions from @filepath@ package.
+                       This warrants consistency with @filepath@ functions.
+                       Requires Template Haskell.
+                     .
+                     * @data-filepath@:
+                       Requires 'Typeable' and Template Haskell.
 Stability:           experimental
 License:             BSD3
 Category:            System
@@ -94,7 +102,7 @@
   Location: http://hub.darcs.net/thielema/pathtype/
 
 Source-Repository this
-  Tag:      0.5.5
+  Tag:      0.6
   Type:     darcs
   Location: http://hub.darcs.net/thielema/pathtype/
 
diff --git a/src/System/Path/Directory.hs b/src/System/Path/Directory.hs
--- a/src/System/Path/Directory.hs
+++ b/src/System/Path/Directory.hs
@@ -166,11 +166,14 @@
 copyFile :: (AbsRelClass ar1, AbsRelClass ar2) => FilePath ar1 -> FilePath ar2 -> IO ()
 copyFile p1 p2 = SD.copyFile (getPathString p1) (getPathString p2)
 
-canonicalizePath :: AbsRelClass ar => Path ar fd -> IO (AbsPath fd)
+canonicalizePath ::
+    (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO (AbsPath fd)
 canonicalizePath p = asPath <$> SD.canonicalizePath (getPathString p)
 
-makeRelativeToCurrentDirectory :: AbsRelClass ar => Path ar fd -> IO (RelPath fd)
-makeRelativeToCurrentDirectory p = asPath <$> SD.makeRelativeToCurrentDirectory (getPathString p)
+makeRelativeToCurrentDirectory ::
+    (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO (RelPath fd)
+makeRelativeToCurrentDirectory p =
+    asPath <$> SD.makeRelativeToCurrentDirectory (getPathString p)
 
 findExecutable :: String -> IO (Maybe AbsFile)
 findExecutable s = fmap asPath <$> SD.findExecutable s
@@ -189,15 +192,18 @@
 ------------------------------------------------------------------------
 -- Permissions
 
-getPermissions :: AbsRelClass ar => Path ar fd -> IO Permissions
+getPermissions ::
+    (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO Permissions
 getPermissions p = SD.getPermissions (getPathString p)
 
-setPermissions :: AbsRelClass ar => Path ar fd -> Permissions -> IO ()
+setPermissions ::
+    (AbsRelClass ar, FileDirClass fd) => Path ar fd -> Permissions -> IO ()
 setPermissions p perms = SD.setPermissions (getPathString p) perms
 
 
 ------------------------------------------------------------------------
 -- Timestamps
 
-getModificationTime :: AbsRelClass ar => Path ar fd -> IO UTCTime
+getModificationTime ::
+    (AbsRelClass ar, FileDirClass fd) => Path ar fd -> IO UTCTime
 getModificationTime p = convertTime <$> SD.getModificationTime (getPathString p)
diff --git a/src/System/Path/Internal.hs b/src/System/Path/Internal.hs
--- a/src/System/Path/Internal.hs
+++ b/src/System/Path/Internal.hs
@@ -116,12 +116,14 @@
 
 import qualified System.Directory as SD
 
-import Control.Arrow (first, (|||), (***))
+import Control.Arrow (first, second, (|||), (***))
+import Control.Monad (guard, mplus)
 import Control.Applicative ((<$>))
 import Control.DeepSeq (NFData(rnf))
-import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intercalate)
+import Data.List (isSuffixOf, isPrefixOf, stripPrefix, intersperse)
 import Data.String (IsString(fromString))
-import Data.Char (isSpace)
+import Data.Maybe (fromMaybe, maybeToList)
+import Data.Char (toLower, isAlpha, isSpace)
 
 import Text.Printf (printf)
 
@@ -136,29 +138,75 @@
 ------------------------------------------------------------------------
 -- Types
 
-data Abs
-data Rel
-data File
-data Dir
+newtype Abs = Abs String deriving (Eq, Ord)
+data Rel = Rel deriving (Eq, Ord)
 
+newtype File = File PathComponent deriving (Eq, Ord)
+data Dir  = Dir deriving (Eq, Ord)
+
 -- | This is the main filepath abstract datatype
-data Path ar fd = PathRoot -- ^ Invariant - this should always have type :: DirPath ar
-                | FileDir !(DirPath ar) !PathComponent -- The fact that we recurse binding fd to Dir
-                                                       -- makes this a "nested datatype"
-                  deriving (Eq, Ord)
+data Path ar fd = Path ar [PathComponent] fd
 
--- Possible GADT version...
---
--- data Path ar fd where
---   AbsRoot :: Path Abs Dir
---   RelRoot :: Path Rel Dir
---   File    :: Path ar Dir -> PathComponent -> Path ar File
---   Dir     :: Path ar Dir -> PathComponent -> Path ar Dir
---
--- ... doesn't presently seem to add much value over non-GADT.
+instance (AbsRelClass ar, FileDirClass fd) => Eq (Path ar fd) where
+    Path ar0 pcs0 fd0 == Path ar1 pcs1 fd1  =
+        (WrapAbsRel ar0, pcs0, WrapFileDir fd0)
+        ==
+        (WrapAbsRel ar1, pcs1, WrapFileDir fd1)
 
-newtype PathComponent = PathComponent String deriving (Eq,Ord)
+instance (AbsRelClass ar, FileDirClass fd) => Ord (Path ar fd) where
+    compare (Path ar0 pcs0 fd0) (Path ar1 pcs1 fd1)  =
+        compare
+            (WrapAbsRel ar0, pcs0, WrapFileDir fd0)
+            (WrapAbsRel ar1, pcs1, WrapFileDir fd1)
 
+
+newtype WrapAbsRel ar = WrapAbsRel {unwrapAbsRel :: ar}
+
+instance (AbsRelClass ar) => Eq (WrapAbsRel ar) where
+    (==) = switchRelation switchAbsRel unwrapAbsRel (==) (==)
+
+instance (AbsRelClass ar) => Ord (WrapAbsRel ar) where
+    compare = switchRelation switchAbsRel unwrapAbsRel compare compare
+
+
+newtype WrapFileDir fd = WrapFileDir {unwrapFileDir :: fd}
+
+instance (FileDirClass fd) => Eq (WrapFileDir fd) where
+    (==) = switchRelation switchFileDir unwrapFileDir (==) (==)
+
+instance (FileDirClass fd) => Ord (WrapFileDir fd) where
+    compare = switchRelation switchFileDir unwrapFileDir compare compare
+
+
+newtype Relation res a = Relation {runRelation :: a -> a -> res}
+
+switchRelation ::
+    (Relation res a -> Relation res b -> Relation res c) ->
+    (wrapped -> c) ->
+    (a -> a -> res) ->
+    (b -> b -> res) ->
+    wrapped -> wrapped -> res
+switchRelation switch unwrap fFile fDir ar0 ar1 =
+    runRelation
+        (switch (Relation fFile) (Relation fDir))
+        (unwrap ar0) (unwrap ar1)
+
+
+newtype PathComponent = PathComponent String
+
+instance Eq PathComponent where
+    PathComponent x == PathComponent y  =
+        if isPosix
+          then x==y
+          else map toLower x == map toLower y
+
+instance Ord PathComponent where
+    compare (PathComponent x) (PathComponent y) =
+        if isPosix
+          then compare x y
+          else compare (map toLower x) (map toLower y)
+
+
 type AbsFile = Path Abs File
 type RelFile = Path Rel File
 type AbsDir  = Path Abs Dir
@@ -172,10 +220,32 @@
 instance NFData PathComponent where
     rnf (PathComponent pc) = rnf pc
 
-instance NFData (Path ar fd) where
-    rnf PathRoot = ()
-    rnf (FileDir d pc) = rnf (d, pc)
+instance NFData Abs where
+    rnf (Abs drive) = rnf drive
 
+instance NFData Rel where
+    rnf Rel = ()
+
+instance NFData File where
+    rnf (File pc) = rnf pc
+
+instance NFData Dir where
+    rnf Dir = ()
+
+instance (AbsRelClass ar, FileDirClass fd) => NFData (Path ar fd) where
+    rnf (Path ar pcs fd) =
+        rnf (absRelPlain rnf rnf ar, pcs, fileDirPlain rnf rnf fd)
+
+absRelPlain :: (AbsRelClass ar) => (Abs -> a) -> (Rel -> a) -> ar -> a
+absRelPlain fAbs fRel =
+    runFuncArg $ switchAbsRel (FuncArg fAbs) (FuncArg fRel)
+
+fileDirPlain :: (FileDirClass fd) => (File -> a) -> (Dir -> a) -> fd -> a
+fileDirPlain fFile fDir =
+    runFuncArg $ switchFileDir (FuncArg fFile) (FuncArg fDir)
+
+newtype FuncArg b a = FuncArg {runFuncArg :: a -> b}
+
 -- I don't think this basic type of fold is appropriate for a nested datatype
 -- pathFold :: a -> (a -> String -> a) -> Path ar fd -> a
 -- pathFold pr f PathRoot = pr
@@ -183,12 +253,17 @@
 
 -- | Map over the components of the path.
 --
--- >> pathMap (map toLower) "/tmp/Reports/SpreadSheets" == "/tmp/reports/spreadsheets"
-pathMap :: (String -> String) -> Path ar fd -> Path ar fd
-pathMap _ PathRoot = PathRoot
-pathMap f (FileDir d pc) = FileDir (pathMap f d) (pcMap f pc)
+-- >> Posix.pathMap (map toLower) "/tmp/Reports/SpreadSheets" == Posix.asAbsDir "/tmp/reports/spreadsheets"
+pathMap :: (FileDirClass fd) => (String -> String) -> Path ar fd -> Path ar fd
+pathMap f (Path ar pcs fd) = Path ar (map (pcMap f) pcs) (fdMap f fd)
 
--- Private fn
+newtype FDMap ar fd = FDMap {runFDMap :: fd -> fd}
+
+fdMap :: (FileDirClass fd) => (String -> String) -> fd -> fd
+fdMap f =
+    runFDMap $
+    switchFileDir (FDMap $ \(File pc) -> File $ pcMap f pc) (FDMap id)
+
 pcMap :: (String -> String) -> PathComponent -> PathComponent
 pcMap f (PathComponent s) = PathComponent (f s)
 
@@ -226,9 +301,9 @@
     switchFileDir :: f File -> f Dir -> f fd
     -- | Will become a top-level function in future
     fileDir :: (FilePath ar -> a) -> (DirPath ar -> a) -> Path ar fd -> a
-    fileDir f g = runFileDir $ switchFileDir (FileDirFunc f) (FileDirFunc g)
+    fileDir f g = runFileDir $ switchFileDir (FileDir f) (FileDir g)
 
-newtype FileDir ar a fd = FileDirFunc {runFileDir :: Path ar fd -> a}
+newtype FileDir ar a fd = FileDir {runFileDir :: Path ar fd -> a}
 
 instance FileDirClass File where switchFileDir f _g = f
 instance FileDirClass Dir  where switchFileDir _f g = g
@@ -245,62 +320,86 @@
 ------------------------------------------------------------------------
 -- Read & Show instances
 
--- >> show (rootDir </> "bla" </> "blub") == "rootDir </> \"bla\" </> \"blub\""
--- >> show (Just (rootDir </> "bla" </> "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")"
--- >> show (currentDir </> "bla" </> "blub") == "currentDir </> \"bla\" </> \"blub\""
--- >> show (Just (currentDir </> "bla" </> "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")"
-instance AbsRelClass ar => Show (Path ar fd) where
-    showsPrec d =
-        let go :: AbsRelClass ar => Path ar fd -> ShowS
-            go x@PathRoot =
-                absRel (const $ showString rootName) (const $ showString currentName) x
-            go (FileDir p (PathComponent pc)) =
-                go p . showChar ' ' .
-                showString combineOperator . showChar ' ' . shows pc
-        in  showParen (d>9) . go
+-- >> show (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") == "rootDir </> \"bla\" </> \"blub\""
+-- >> show (Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")"
+-- >> show (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") == "currentDir </> \"bla\" </> \"blub\""
+-- >> show (Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")"
+-- >> show (Windows.asAbsDir "c:" Windows.</> "bla" Windows.</> Windows.asRelFile "blub") == "asAbsDir \"c:\" </> \"bla\" </> \"blub\""
+-- >> show (Just (Windows.asAbsDir "c:\\" Windows.</> "bla" Windows.</> Windows.asRelFile "blub")) == "Just (asAbsDir \"c:\" </> \"bla\" </> \"blub\")"
+instance (AbsRelClass ar, FileDirClass fd) => Show (Path ar fd) where
+    showsPrec d x =
+        case pathComponents x of
+            (ar, pcs) ->
+                showParen (d>9) $
+                foldr (.) id $
+                intersperse
+                    (showChar ' ' .
+                     showString combineOperator . showChar ' ') $
+                absRelPlain
+                    (\(Abs drive) ->
+                        if null drive
+                          then showString rootName
+                          else showString absDirName .
+                               showString drive .
+                               showChar '"')
+                    (const $ showString currentName)
+                    ar :
+                map (\(PathComponent pc) -> shows pc) pcs
 
--- >> read (show (rootDir </> "bla" </> "blub")) == rootDir </> "bla" </> "blub"
--- >> read (show (Just (rootDir </> "bla" </> "blub"))) == Just (rootDir </> "bla" </> "blub")
--- >> read (show (currentDir </> "bla" </> "blub")) == currentDir </> "bla" </> "blub"
--- >> read (show (Just (currentDir </> "bla" </> "blub"))) == Just (currentDir </> "bla" </> "blub")
-instance AbsRelClass ar => Read (Path ar fd) where
+-- >> let path = Posix.rootDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path
+-- >> let path = Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path
+-- >> let path = Posix.currentDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path
+-- >> let path = Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path
+-- >> let path = Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub" in read (show path) == path
+-- >> let path = Just (Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub") in read (show path) == path
+instance (AbsRelClass ar, FileDirClass fd) => Read (Path ar fd) where
     readsPrec d = readParen (d>9) $ \str ->
-        let go :: AbsRelClass ar => Path ar Dir -> ReadS (Path ar fd)
-            go path s0 =
+        let go :: ReadS [PathComponent]
+            go s0 =
                 case stripPrefix combineOperator $ dropWhile isSpace s0 of
-                    Nothing -> [(relaxDir path, s0)]
+                    Nothing -> [([], s0)]
                     Just s1 -> do
                         (pc, s2) <- reads s1
-                        go (FileDir path (PathComponent pc)) s2
-            result = do
-                let required = absRel (const rootName) (const currentName) $ fst $ head result
-                maybe [] (go PathRoot) $
-                    stripPrefix required $ dropWhile isSpace str
-        in  result
+                        (pcs, s3) <- go s2
+                        return (PathComponent pc : pcs, s3)
+        in  do
+                (ar, s0) <- maybeToList $ readsSplitDrive $ dropWhile isSpace str
+                (pcs, s1) <- go s0
+                path <- maybeToList $ maybePathFromComponents ar pcs
+                return (path, s1)
 
-relaxDir :: Path ar Dir -> Path ar fd
-relaxDir PathRoot = PathRoot
-relaxDir (FileDir p pc) = FileDir p pc
+newtype
+    ReadsSplitDrive ar =
+        ReadsSplitDrive {runReadsSplitDrive :: Maybe (ar, String)}
 
+readsSplitDrive :: (AbsRelClass ar) => String -> Maybe (ar, String)
+readsSplitDrive str0 =
+    runReadsSplitDrive $
+    switchAbsRel
+        (ReadsSplitDrive $
+            (fmap ((,) (Abs "")) $ stripPrefix rootName str0)
+            `mplus`
+            do  str1 <- stripPrefix absDirName str0
+                (drive, '"':str2) <- Just $ break ('"'==) str1
+                return (Abs drive, str2))
+        (ReadsSplitDrive $
+            fmap ((,) Rel) $ stripPrefix currentName str0)
+
 -- | Convert the 'Path' into a plain 'String' as required for OS calls.
-getPathString :: AbsRelClass ar => Path ar fd -> String
+getPathString :: (AbsRelClass ar, FileDirClass fd) => Path ar fd -> String
 getPathString = flip getPathStringS ""
 
-getPathStringS :: AbsRelClass ar => Path ar fd -> ShowS
-getPathStringS =
-    let go :: AbsRelClass ar => Path ar fd -> ShowS
-        go x@PathRoot =
-            absRel
-                (const $ showChar pathSeparator)
-                (const $ showString currentDirComponent) x
-        -- we need the clause below so that we don't duplicate the pathSeparator after an abs
-        -- root and we don't want to display a "./" prefix on relative paths
-        go (FileDir p@PathRoot (PathComponent pc)) =
-            absRel (const $ showChar pathSeparator) (const id) p .
-            showString pc
-        go (FileDir p (PathComponent pc)) =
-            go p . showChar pathSeparator . showString pc
-    in  go
+getPathStringS :: (AbsRelClass ar, FileDirClass fd) => Path ar fd -> ShowS
+getPathStringS x =
+    case pathComponents x of
+        (ar, []) ->
+            absRelPlain
+                (\(Abs drive) -> showString drive . showChar pathSeparator)
+                (const $ showString currentDirComponent) ar
+        (ar, pcs) ->
+            foldr (.) id $ intersperse (showChar pathSeparator) $
+            absRelPlain (\(Abs drive) -> (showString drive :)) (const id) ar $
+            map (\(PathComponent pc) -> showString pc) pcs
 
 prop_asPath_getPathString :: AbsFile -> Property
 prop_asPath_getPathString p = property $ p == asPath (getPathString p)
@@ -309,8 +408,8 @@
 ------------------------------------------------------------------------
 -- Windows / Posix
 
-_isPosix :: Bool
-_isPosix = not isWindows
+isPosix :: Bool
+isPosix = not isWindows
 
 isWindows :: Bool
 isWindows = IS_WINDOWS
@@ -319,10 +418,10 @@
 -- Constants
 
 rootDir :: AbsDir
-rootDir = PathRoot
+rootDir = Path (Abs "") [] Dir
 
 currentDir :: RelDir
-currentDir = PathRoot
+currentDir = Path Rel [] Dir
 
 rootName :: String
 rootName = "rootDir"
@@ -333,6 +432,8 @@
 currentDirComponent :: String
 currentDirComponent = "."
 
+absDirName :: String
+absDirName = "asAbsDir \""
 
 ------------------------------------------------------------------------
 -- Unchecked Construction Functions
@@ -341,70 +442,82 @@
 -- | Use a 'String' as a 'Path' whose type is determined
 --   by its context.
 --
--- >> asPath "/tmp" == "/tmp"
--- >> asPath "file.txt" == "file.txt"
--- >> isAbsolute (asPath "/tmp" :: AbsDir) == True
--- >> isAbsolute (asPath "/tmp" :: RelDir) == False
--- >> getPathString (asPath "/tmp" :: AbsDir) == "/tmp"
--- >> getPathString (asPath "/tmp" :: RelDir) == "tmp"
-asPath :: String -> Path ar fd
-asPath = mkPathFromComponents . mkPathComponents
+-- >> Posix.asPath "/tmp" == Posix.asAbsDir "/tmp"
+-- >> Posix.asPath "file.txt" == Posix.asRelFile "file.txt"
+-- >> Posix.isAbsolute (Posix.asAbsDir "/tmp")
+-- >> Posix.isRelative (Posix.asRelDir "/tmp")
+-- >> Posix.getPathString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp"
+-- >> Posix.getPathString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp"
+-- >> Windows.getPathString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp"
+-- >> Windows.getPathString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp"
+-- >> Windows.getPathString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp"
+asPath :: (AbsRelClass ar, FileDirClass fd) => String -> Path ar fd
+asPath = uncurry mkPathFromComponents . mkPathComponents
 
+newtype AbsRelDefault ar = AbsRelDefault {getAbsRelDefault :: ar}
+
+absRelDefault :: (AbsRelClass ar) => ar
+absRelDefault =
+    getAbsRelDefault $ switchAbsRel (AbsRelDefault $ Abs "") (AbsRelDefault Rel)
+
+
 -- | Use a 'String' as a 'RelFile'. No checking is done.
 --
--- >> getPathString (asRelFile "file.txt") == "file.txt"
--- >> getPathString (asRelFile "/file.txt") == "file.txt"
--- >> getPathString (asRelFile "tmp") == "tmp"
--- >> getPathString (asRelFile "/tmp") == "tmp"
+-- >> Posix.getPathString (Posix.asRelFile "file.txt") == "file.txt"
+-- >> Posix.getPathString (Posix.asRelFile "/file.txt") == "file.txt"
+-- >> Posix.getPathString (Posix.asRelFile "tmp") == "tmp"
+-- >> Posix.getPathString (Posix.asRelFile "/tmp") == "tmp"
 asRelFile :: String -> RelFile
 asRelFile = asPath
 
 -- | Use a 'String' as a 'RelDir'. No checking is done.
 --
--- >> getPathString (asRelDir ".") == "."
--- >> getPathString (asRelDir "file.txt") == "file.txt"
--- >> getPathString (asRelDir "/file.txt") == "file.txt"
--- >> getPathString (asRelDir "tmp") == "tmp"
--- >> getPathString (asRelDir "/tmp") == "tmp"
+-- >> Posix.getPathString (Posix.asRelDir ".") == "."
+-- >> Posix.getPathString (Posix.asRelDir "file.txt") == "file.txt"
+-- >> Posix.getPathString (Posix.asRelDir "/file.txt") == "file.txt"
+-- >> Posix.getPathString (Posix.asRelDir "tmp") == "tmp"
+-- >> Posix.getPathString (Posix.asRelDir "/tmp") == "tmp"
 asRelDir :: String -> RelDir
 asRelDir = asPath
 
 -- | Use a 'String' as an 'AbsFile'. No checking is done.
 --
--- >> getPathString (asAbsFile "file.txt") == "/file.txt"
--- >> getPathString (asAbsFile "/file.txt") == "/file.txt"
--- >> getPathString (asAbsFile "tmp") == "/tmp"
--- >> getPathString (asAbsFile "/tmp") == "/tmp"
+-- >> Posix.getPathString (Posix.asAbsFile "file.txt") == "/file.txt"
+-- >> Posix.getPathString (Posix.asAbsFile "/file.txt") == "/file.txt"
+-- >> Posix.getPathString (Posix.asAbsFile "tmp") == "/tmp"
+-- >> Posix.getPathString (Posix.asAbsFile "/tmp") == "/tmp"
 asAbsFile :: String -> AbsFile
 asAbsFile = asPath
 
 -- | Use a 'String' as an 'AbsDir'. No checking is done.
 --
--- >> getPathString (asAbsDir "file.txt") == "/file.txt"
--- >> getPathString (asAbsDir "/file.txt") == "/file.txt"
--- >> getPathString (asAbsDir "tmp") == "/tmp"
--- >> getPathString (asAbsDir "/tmp") == "/tmp"
+-- >> Posix.getPathString (Posix.asAbsDir "file.txt") == "/file.txt"
+-- >> Posix.getPathString (Posix.asAbsDir "/file.txt") == "/file.txt"
+-- >> Posix.getPathString (Posix.asAbsDir "tmp") == "/tmp"
+-- >> Posix.getPathString (Posix.asAbsDir "/tmp") == "/tmp"
 asAbsDir :: String -> AbsDir
 asAbsDir = asPath
 
 -- | Use a 'String' as a 'RelPath fd'. No checking is done.
-asRelPath :: String -> RelPath fd
+asRelPath :: (FileDirClass fd) => String -> RelPath fd
 asRelPath = asPath
 
 -- | Use a 'String' as an 'AbsPath fd'. No checking is done.
-asAbsPath :: String -> AbsPath fd
+asAbsPath :: (FileDirClass fd) => String -> AbsPath fd
 asAbsPath = asPath
 
 -- | Use a 'String' as a 'FilePath ar'. No checking is done.
-asFilePath :: String -> FilePath ar
+asFilePath :: (AbsRelClass ar) => String -> FilePath ar
 asFilePath = asPath
 
 -- | Use a 'String' as a 'DirPath ar'. No checking is done.
-asDirPath :: String -> DirPath ar
+asDirPath :: (AbsRelClass ar) => String -> DirPath ar
 asDirPath = asPath
 
 -- | Allow use of OverloadedStrings if desired
-instance IsString (Path ar fd) where fromString = asPath
+instance
+    (AbsRelClass ar, FileDirClass fd) =>
+        IsString (Path ar fd) where fromString = asPath
 
 ------------------------------------------------------------------------
 -- Checked Construction Functions
@@ -412,9 +525,13 @@
 -- | Examines the supplied string and constructs an absolute or
 -- relative path as appropriate.
 --
--- >> mkPathAbsOrRel "/tmp" == Left (asAbsDir "/tmp")
--- >> mkPathAbsOrRel  "tmp" == Right (asRelDir "tmp")
-mkPathAbsOrRel :: String -> Either (AbsPath fd) (RelPath fd)
+-- >> Posix.mkPathAbsOrRel "/tmp" == Left (Posix.asAbsDir "/tmp")
+-- >> Posix.mkPathAbsOrRel  "tmp" == Right (Posix.asRelDir "tmp")
+-- >> Windows.mkPathAbsOrRel "\\tmp" == Left (Windows.asAbsDir "\\tmp")
+-- >> Windows.mkPathAbsOrRel "d:\\tmp" == Left (Windows.asAbsDir "d:\\tmp")
+-- >> Windows.mkPathAbsOrRel "tmp" == Right (Windows.asRelDir "tmp")
+mkPathAbsOrRel ::
+    (FileDirClass fd) => String -> Either (AbsPath fd) (RelPath fd)
 mkPathAbsOrRel s =
     if isAbsoluteString s
       then Left $ asAbsPath s
@@ -437,39 +554,88 @@
 -- | Convert a 'String' into an 'AbsPath' by interpreting it as
 --   relative to the supplied directory if necessary.
 --
--- >> mkAbsPath "/tmp" "foo.txt" == "/tmp/foo.txt"
--- >> mkAbsPath "/tmp" "/etc/foo.txt" == "/etc/foo.txt"
-mkAbsPath :: AbsDir -> String -> AbsPath fd
+-- >> Posix.mkAbsPath "/tmp" "foo.txt" == Posix.asAbsFile "/tmp/foo.txt"
+-- >> Posix.mkAbsPath "/tmp" "/etc/foo.txt" == Posix.asAbsFile "/etc/foo.txt"
+mkAbsPath :: (FileDirClass fd) => AbsDir -> String -> AbsPath fd
 mkAbsPath d = (id ||| makeAbsolute d) . mkPathAbsOrRel
 
 -- | Convert a 'String' into an 'AbsPath' by interpreting it as
 --   relative to the cwd if necessary.
-mkAbsPathFromCwd :: String -> IO (AbsPath fd)
+mkAbsPathFromCwd :: (FileDirClass fd) => String -> IO (AbsPath fd)
 mkAbsPathFromCwd = (return ||| makeAbsoluteFromCwd) . mkPathAbsOrRel
 
 
 ------------------------------------------------------------------------
 -- Internal Functions for PathComponent manipulation
 
-mkPathFromComponents :: [PathComponent] -> Path ar fd
-mkPathFromComponents pcs =
-    case reverse pcs of
-      [] -> PathRoot
-      p:ps -> FileDir (foldr (flip FileDir) PathRoot ps) p
+mkPathFromComponents :: (FileDirClass fd) => ar -> [PathComponent] -> Path ar fd
+mkPathFromComponents ar pcs =
+    switchFileDir
+        (fromMaybe (Path ar [] $ File $ PathComponent "") $
+         mkFilePathFromComponents ar pcs)
+        (mkDirPathFromComponents ar pcs)
 
-mkPathComponents :: String -> [PathComponent]
-mkPathComponents xs =
-    case break isPathSeparator (dropWhile isPathSeparator xs) of
-      ("","")  -> []
-      (s,rest) -> PathComponent s : mkPathComponents rest
+maybePathFromComponents ::
+    (FileDirClass fd) => ar -> [PathComponent] -> Maybe (Path ar fd)
+maybePathFromComponents ar pcs =
+    getFunctorPath $
+    switchFileDir
+        (FunctorPath $ mkFilePathFromComponents ar pcs)
+        (FunctorPath $ Just $ mkDirPathFromComponents ar pcs)
 
-pathComponents :: Path ar fd -> [PathComponent]
-pathComponents PathRoot = []
-pathComponents (FileDir p pc) = pathComponents p ++ [pc]
+newtype
+    FunctorPath f ar fd =
+        FunctorPath {getFunctorPath :: f (Path ar fd)}
 
-prop_mkPathFromComponents_pathComponents :: AbsFile -> Property
+mkDirPathFromComponents :: ar -> [PathComponent] -> Path ar Dir
+mkDirPathFromComponents ar pcs = Path ar pcs Dir
+
+mkFilePathFromComponents :: ar -> [PathComponent] -> Maybe (Path ar File)
+mkFilePathFromComponents _ [] = Nothing
+mkFilePathFromComponents ar0 (q:qs) =
+    let mapPathDirs f ~(Path ar pcs fd) = Path ar (f pcs) fd
+        go p [] = Path ar0 [] (File p)
+        go p0 (p1:ps) = mapPathDirs (p0:) $ go p1 ps
+    in  Just $ go q qs
+
+mkPathComponents :: (AbsRelClass ar) => String -> (ar, [PathComponent])
+mkPathComponents =
+    let go xs =
+            case break isPathSeparator $ dropWhile isPathSeparator xs of
+                ("","") -> []
+                (s,rest) -> s : go rest
+        split [] = (absRelDefault, [])
+        split (pc:pcs) =
+            second (map PathComponent) $
+            case splitDrive pc of
+                (drive, "") -> (drive, pcs)
+                (drive, pc0) -> (drive, pc0:pcs)
+    in  split . go
+
+newtype SplitDrive ar = SplitDrive {runSplitDrive :: (ar, String)}
+
+splitDrive :: (AbsRelClass ar) => String -> (ar, String)
+splitDrive str =
+    runSplitDrive $
+    switchAbsRel
+        (SplitDrive $ first Abs $
+         if isPosix
+           then ("", str)
+           else
+               case break (':'==) str of
+                   (drive, ':':rest) -> (drive++":", rest)
+                   _ -> ("", str))
+        (SplitDrive (Rel, str))
+
+pathComponents :: (FileDirClass fd) => Path ar fd -> (ar, [PathComponent])
+pathComponents (Path ar pcs fd) = (ar, pcs ++ fileDirComponent fd)
+
+fileDirComponent :: (FileDirClass fd) => fd -> [PathComponent]
+fileDirComponent = fileDirPlain (\(File pc) -> [pc]) (\Dir -> [])
+
+prop_mkPathFromComponents_pathComponents :: AbsDir -> Property
 prop_mkPathFromComponents_pathComponents p =
-    property $ mkPathFromComponents (pathComponents p) == p
+    property $ uncurry mkPathFromComponents (pathComponents p) == p
 
 
 
@@ -480,10 +646,16 @@
 combineOperator = "</>"
 
 -- | Infix variant of 'combine'.
+--
+-- >> Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelFile "file.txt") == "/tmp/file.txt"
+-- >> Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "/tmp/dir/file.txt"
+-- >> Posix.getPathString (Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "dir/file.txt"
+-- >> Windows.getPathString (Windows.asAbsDir "\\tmp" Windows.</> Windows.asRelFile "file.txt") == "\\tmp\\file.txt"
+-- >> Windows.getPathString (Windows.asAbsDir "c:\\tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt"
+-- >> Windows.getPathString (Windows.asAbsDir "c:" Windows.</> Windows.asRelDir "tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt"
+-- >> Windows.getPathString (Windows.asRelDir "dir" Windows.</> Windows.asRelFile "file.txt") == "dir\\file.txt"
 (</>) :: DirPath ar -> RelPath fd -> Path ar fd
-PathRoot         </> PathRoot       = PathRoot
-(FileDir dp dpc) </> PathRoot       = FileDir dp dpc
-d                </> (FileDir p pc) = FileDir (d </> p) pc
+(Path ar pcs0 Dir) </> (Path Rel pcs1 fd) = Path ar (pcs0 ++ pcs1) fd
 
 -- | Infix variant of 'addExtension'.
 --   We only allow files (and not directories) to have extensions added
@@ -494,17 +666,17 @@
 --   directories, and so we provide a function that is more flexible:
 --   'genericAddExtension'.
 (<.>) :: FilePath ar -> String -> FilePath ar
-(<.>) = genericAddExtension
+Path ar pcs (File pc) <.> ext = Path ar pcs (File $ addExtensionPC pc ext)
 
 -- | Add an extension, even if there is already one there.
 --   E.g. @addExtension \"foo.txt\" \"bat\" -> \"foo.txt.bat\"@.
 --
--- >> addExtension "file.txt" "bib" == "file.txt.bib"
--- >> addExtension "file." ".bib" == "file..bib"
--- >> addExtension "file" ".bib" == "file.bib"
--- >> addExtension "" "bib" == ".bib"
--- >> addExtension "" ".bib" == ".bib"
--- >> takeFileName (addExtension "" "ext") == ".ext"
+-- >> Posix.addExtension (Posix.asRelFile "file.txt") "bib" == "file.txt.bib"
+-- >> Posix.addExtension (Posix.asRelFile "file.") ".bib" == "file..bib"
+-- >> Posix.addExtension (Posix.asRelFile "file") ".bib" == "file.bib"
+-- >> Posix.addExtension (Posix.asRelFile "") "bib" == ".bib"
+-- >> Posix.addExtension (Posix.asRelFile "") ".bib" == ".bib"
+-- >> Posix.takeFileName (Posix.addExtension (Posix.asRelFile "") "ext") == ".ext"
 addExtension :: FilePath ar -> String -> FilePath ar
 addExtension = (<.>)
 
@@ -516,67 +688,69 @@
 
 -- | Remove last extension, and the \".\" preceding it.
 --
--- >> dropExtension x == fst (splitExtension x)
+-- >> Posix.dropExtension x == fst (Posix.splitExtension x)
 dropExtension :: FilePath ar -> FilePath ar
 dropExtension = fst . splitExtension
 
 -- | Drop all extensions
 --
--- >> not $ hasAnExtension (dropExtensions x)
+-- >> not $ Posix.hasAnExtension (Posix.dropExtensions x)
 dropExtensions :: FilePath ar -> FilePath ar
 dropExtensions = fst . splitExtensions
 
 -- | Synonym for 'takeDirectory'
-dropFileName :: Path ar fd -> DirPath ar
+dropFileName :: FilePath ar -> DirPath ar
 dropFileName = fst . splitFileName
 
 
 -- | Set the extension of a file, overwriting one if already present.
 --
--- >> replaceExtension "file.txt" ".bob" == "file.bob"
--- >> replaceExtension "file.txt" "bob" == "file.bob"
--- >> replaceExtension "file" ".bob" == "file.bob"
--- >> replaceExtension "file.txt" "" == "file"
--- >> replaceExtension "file.fred.bob" "txt" == "file.fred.txt"
+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") ".bob" == "file.bob"
+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") "bob" == "file.bob"
+-- >> Posix.replaceExtension (Posix.asRelFile "file") ".bob" == "file.bob"
+-- >> Posix.replaceExtension (Posix.asRelFile "file.txt") "" == "file"
+-- >> Posix.replaceExtension (Posix.asRelFile "file.fred.bob") "txt" == "file.fred.txt"
 replaceExtension :: FilePath ar -> String -> FilePath ar
 replaceExtension p ext = dropExtension p <.> ext
 
-replaceBaseName :: Path ar fd -> String -> Path ar fd
-replaceBaseName p bn = takeDirectory p </> (asPath bn `genericAddExtension` genericTakeExtension p)
+replaceBaseName :: FilePath ar -> String -> FilePath ar
+replaceBaseName (Path ar pcs (File pc)) bn =
+    Path ar pcs $ File $
+    addExtensionPC (PathComponent bn) $ snd $ splitExtensionPC pc
 
-replaceDirectory :: Path ar1 fd -> DirPath ar2 -> Path ar2 fd
-replaceDirectory p d = d </> takeFileName p
+replaceDirectory :: FilePath ar1 -> DirPath ar2 -> FilePath ar2
+replaceDirectory (Path _ _ fd) (Path ar pcs _) = Path ar pcs fd
 
-replaceFileName :: Path ar fd -> String -> Path ar fd
-replaceFileName p fn = takeDirectory p </> asPath fn
+replaceFileName :: FilePath ar -> String -> FilePath ar
+replaceFileName (Path ar pcs _) fn = Path ar pcs (File (PathComponent fn))
 
 
 -- | Split on the extension. 'addExtension' is the inverse.
 --
--- >> uncurry (<.>) (splitExtension x) == x
--- >> uncurry addExtension (splitExtension x) == x
--- >> splitExtension "file.txt" == ("file",".txt")
--- >> splitExtension "file" == ("file","")
--- >> splitExtension "file/file.txt" == ("file/file",".txt")
--- >> splitExtension "file.txt/boris" == ("file.txt/boris","")
--- >> splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")
--- >> splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")
+-- >> uncurry (<.>) (Posix.splitExtension x) == x
+-- >> uncurry Posix.addExtension (Posix.splitExtension x) == x
+-- >> Posix.splitExtension (Posix.asRelFile "file.txt") == ("file",".txt")
+-- >> Posix.splitExtension (Posix.asRelFile "file") == ("file","")
+-- >> Posix.splitExtension (Posix.asRelFile "file/file.txt") == ("file/file",".txt")
+-- >> Posix.splitExtension (Posix.asRelFile "file.txt/boris") == ("file.txt/boris","")
+-- >> Posix.splitExtension (Posix.asRelFile "file.txt/boris.ext") == ("file.txt/boris",".ext")
+-- >> Posix.splitExtension (Posix.asRelFile "file/path.txt.bob.fred") == ("file/path.txt.bob",".fred")
 splitExtension :: FilePath ar -> (FilePath ar, String)
-splitExtension = genericSplitExtension
+splitExtension (Path ar pcs (File pc)) =
+    first (Path ar pcs . File) $ splitExtensionPC pc
 
 -- | Split on all extensions
 --
--- >> splitExtensions "file.tar.gz" == ("file",".tar.gz")
+-- >> Posix.splitExtensions (Posix.asRelFile "file.tar.gz") == ("file",".tar.gz")
 splitExtensions :: FilePath ar -> (FilePath ar, String)
-splitExtensions = genericSplitExtensions
+splitExtensions (Path ar pcs (File pc)) =
+    first (Path ar pcs . File) $ splitExtensionsPC pc
 
 prop_split_combineExt :: AbsFile -> Property
 prop_split_combineExt p = property $ p == uncurry (<.>) (splitExtension p)
 
--- | Path must not be empty
-splitFileName :: Path ar fd -> (DirPath ar, RelPath fd)
-splitFileName (FileDir p pc) = (p, mkPathFromComponents [pc])
-splitFileName PathRoot = error "splitFileName: empty path"
+splitFileName :: FilePath ar -> (DirPath ar, RelFile)
+splitFileName (Path ar pcs fd) = (Path ar pcs Dir, Path Rel [] fd)
 
 prop_split_combine :: AbsFile -> Property
 prop_split_combine p = property $ uncurry combine (splitFileName p) == p
@@ -584,37 +758,36 @@
 
 -- | Get the basename of a file
 --
--- >> takeBaseName "/tmp/somedir/myfile.txt" == "myfile"
--- >> takeBaseName "./myfile.txt" == "myfile"
--- >> takeBaseName "myfile.txt" == "myfile"
-takeBaseName :: Path ar fd -> RelPath fd
-takeBaseName = takeFileName . genericDropExtension
+-- >> Posix.takeBaseName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile"
+-- >> Posix.takeBaseName (Posix.asRelFile "./myfile.txt") == "myfile"
+-- >> Posix.takeBaseName (Posix.asRelFile "myfile.txt") == "myfile"
+takeBaseName :: FilePath ar -> RelFile
+takeBaseName = takeFileName . dropExtension
 
-takeDirectory :: Path ar fd -> DirPath ar
+takeDirectory :: FilePath ar -> DirPath ar
 takeDirectory = fst . splitFileName
 
 -- | Get the extension of a file, returns @\"\"@ for no extension, @.ext@ otherwise.
 --
--- >> takeExtension x == snd (splitExtension x)
--- >> takeExtension (addExtension x "ext") == ".ext"
--- >> takeExtension (replaceExtension x "ext") == ".ext"
+-- >> Posix.takeExtension x == snd (Posix.splitExtension x)
+-- >> Posix.takeExtension (Posix.addExtension x "ext") == ".ext"
+-- >> Posix.takeExtension (Posix.replaceExtension x "ext") == ".ext"
 takeExtension :: FilePath ar -> String
 takeExtension = snd . splitExtension
 
 -- | Get all extensions
 --
--- >> takeExtensions "file.tar.gz" == ".tar.gz"
+-- >> Posix.takeExtensions (Posix.asRelFile "file.tar.gz") == ".tar.gz"
 takeExtensions :: FilePath ar -> String
 takeExtensions = snd . splitExtensions
 
 -- | Get the filename component of a file path (ie stripping all parent dirs)
 --
--- >> takeFileName "/tmp/somedir/myfile.txt" == "myfile.txt"
--- >> takeFileName "./myfile.txt" == "myfile.txt"
--- >> takeFileName "myfile.txt" == "myfile.txt"
-takeFileName :: Path ar fd -> RelPath fd
-takeFileName PathRoot = PathRoot -- becomes a relative root
-takeFileName (FileDir _ pc) = FileDir PathRoot pc
+-- >> Posix.takeFileName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile.txt"
+-- >> Posix.takeFileName (Posix.asRelFile "./myfile.txt") == "myfile.txt"
+-- >> Posix.takeFileName (Posix.asRelFile "myfile.txt") == "myfile.txt"
+takeFileName :: FilePath ar -> RelFile
+takeFileName (Path _ _ fd) = Path Rel [] fd
 
 prop_takeFileName_end :: AbsFile -> Property
 prop_takeFileName_end p = property $ show (takeFileName p) `isSuffixOf` show p
@@ -625,51 +798,65 @@
 
 -- | Check whether two strings are equal as file paths.
 --
--- >> equalFilePath "/tmp/" "/tmp" == True
--- >> equalFilePath "/tmp"  "tmp"  == False
+-- >>       Posix.equalFilePath "/tmp/" "/tmp"
+-- >> not $ Posix.equalFilePath "/tmp" "tmp"
+-- >>       Windows.equalFilePath "file" "File"
+-- >> not $ Windows.equalFilePath "file" "dir"
 equalFilePath :: String -> String -> Bool
 equalFilePath s1 s2 =
-    isAbsoluteString s1 == isAbsoluteString s2 && asPath s1 == asPath s2
+    let abs1 = isAbsoluteString s1
+        abs2 = isAbsoluteString s2
+    in  abs1 == abs2 &&
+        if abs1
+          then asAbsDir s1 == asAbsDir s2
+          else asRelDir s1 == asRelDir s2
 
--- | Constructs a 'Path' from a list of components.
+-- | Constructs a 'RelPath' from a list of components.
+--   It is an unchecked error if the path components contain path separators.
+--   It is an unchecked error if a 'RelFile' path is empty.
 --
--- >> joinPath ["/tmp","someDir","file.txt"] == "/tmp/someDir/file.txt"
--- >> joinPath ["/tmp","someDir","file.txt"] == asRelFile "tmp/someDir/file.txt"
-joinPath :: [String] -> Path ar fd
-joinPath = asPath . intercalate [pathSeparator]
+-- >> Posix.joinPath ["tmp","someDir","dir"] == Posix.asRelDir "tmp/someDir/dir"
+-- >> Posix.joinPath ["tmp","someDir","file.txt"] == Posix.asRelFile "tmp/someDir/file.txt"
+joinPath :: (FileDirClass fd) => [String] -> RelPath fd
+joinPath = mkPathFromComponents Rel . map PathComponent
 
 -- | Currently just transforms:
 --
--- >> normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file"
+-- >> Posix.normalise "/tmp/fred/./jim/./file" == Posix.asAbsFile "/tmp/fred/jim/file"
 normalise :: Path ar fd -> Path ar fd
-normalise =
-    mkPathFromComponents .
-    filter (/= PathComponent currentDirComponent) .
-    pathComponents
+normalise (Path ar pcs fd) =
+    Path ar (filter (PathComponent currentDirComponent /=) pcs) fd
 
 -- | Deconstructs a path into its components.
 --
--- >> splitPath (asAbsDir "/tmp/someDir/mydir.dir") == (["tmp","someDir","mydir.dir"], Nothing)
--- >> splitPath (asAbsFile "/tmp/someDir/myfile.txt") == (["tmp","someDir"], Just "myfile.txt")
-splitPath :: FileDirClass fd => Path ar fd -> ([RelDir], Maybe RelFile)
-splitPath PathRoot = ([],Nothing)
-splitPath p@(FileDir d pc) =
-    first (map (FileDir PathRoot)) $
-    fileDir
-        (\ _ -> (pathComponents d, Just (FileDir PathRoot pc)))
-        (\ _ -> (pathComponents p, Nothing))
-        p
+-- >> Posix.splitPath (Posix.asAbsDir "/tmp/someDir/mydir.dir") == (True, ["tmp","someDir","mydir.dir"], Nothing)
+-- >> Posix.splitPath (Posix.asAbsFile "/tmp/someDir/myfile.txt") == (True, ["tmp","someDir"], Just "myfile.txt")
+splitPath ::
+    (AbsRelClass ar, FileDirClass fd) =>
+    Path ar fd -> (Bool, [RelDir], Maybe RelFile)
+splitPath (Path ar pcs fd) =
+    (isAbsolutePlain ar,
+     map (\pc -> Path Rel [pc] Dir) pcs,
+     maybeFileDir fd)
 
+isAbsolutePlain :: (AbsRelClass ar) => ar -> Bool
+isAbsolutePlain = absRelPlain (const True) (const False)
+
+maybeFileDir :: (FileDirClass fd) => fd -> Maybe RelFile
+maybeFileDir = fileDirPlain (Just . Path Rel []) (\Dir -> Nothing)
+
 -- | This function can be used to construct a relative path by removing
 --   the supplied 'AbsDir' from the front. It is a runtime 'error' if the
 --   supplied 'AbsPath' doesn't start with the 'AbsDir'.
 --
--- >> makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == asRelFile "anotherdir/file.txt"
--- >> makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == asRelDir "anotherdir/dir"
-makeRelative :: AbsDir -> AbsPath fd -> RelPath fd
-makeRelative relTo orig =
-    maybe (error msg) mkPathFromComponents $
-    stripPrefix (pathComponents relTo) (pathComponents orig)
+-- >> Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == Posix.asRelFile "anotherdir/file.txt"
+-- >> Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == Posix.asRelDir "anotherdir/dir"
+-- >> Windows.makeRelative "c:\\tmp\\somedir" "c:\\Tmp\\SomeDir\\AnotherDir\\File.txt" == Windows.asRelFile "AnotherDir\\File.txt"
+-- >> Windows.makeRelative "c:\\tmp\\somedir" "c:\\tmp\\somedir\\anotherdir\\dir" == Windows.asRelDir "anotherdir\\dir"
+makeRelative :: (FileDirClass fd) => AbsDir -> AbsPath fd -> RelPath fd
+makeRelative relTo@(Path relToAR relToPCs Dir) orig@(Path origAR origPCs fd) =
+    maybe (error msg) (flip (Path Rel) fd) $
+    guard (relToAR == origAR) >> stripPrefix relToPCs origPCs
   where
     msg =
         printf "System.Path can't make (%s) relative to (%s)"
@@ -678,9 +865,9 @@
 -- | Joins an absolute directory with a relative path to construct a
 --   new absolute path.
 --
--- >> makeAbsolute "/tmp" "file.txt"      == asAbsFile "/tmp/file.txt"
--- >> makeAbsolute "/tmp" "adir/file.txt" == asAbsFile "/tmp/adir/file.txt"
--- >> makeAbsolute "/tmp" "adir/dir"      == asAbsDir "/tmp/adir/dir"
+-- >> Posix.makeAbsolute "/tmp" "file.txt"      == Posix.asAbsFile "/tmp/file.txt"
+-- >> Posix.makeAbsolute "/tmp" "adir/file.txt" == Posix.asAbsFile "/tmp/adir/file.txt"
+-- >> Posix.makeAbsolute "/tmp" "adir/dir"      == Posix.asAbsDir "/tmp/adir/dir"
 makeAbsolute :: AbsDir -> RelPath fd -> AbsPath fd
 makeAbsolute = genericMakeAbsolute
 
@@ -692,10 +879,10 @@
 -- | As for 'makeAbsolute', but for use when the path may already be
 --   absolute (in which case it is left unchanged).
 --
--- >> genericMakeAbsolute "/tmp" (asRelFile "file.txt")       == "/tmp/file.txt"
--- >> genericMakeAbsolute "/tmp" (asRelFile "adir/file.txt")  == "/tmp/adir/file.txt"
--- >> genericMakeAbsolute "/tmp" (asAbsFile "adir/file.txt")  == "/adir/file.txt"
--- >> genericMakeAbsolute "/tmp" (asAbsFile "/adir/file.txt") == "/adir/file.txt"
+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "file.txt")       == "/tmp/file.txt"
+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "adir/file.txt")  == "/tmp/adir/file.txt"
+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "adir/file.txt")  == "/adir/file.txt"
+-- >> Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "/adir/file.txt") == "/adir/file.txt"
 genericMakeAbsolute :: AbsRelClass ar => AbsDir -> Path ar fd -> AbsPath fd
 genericMakeAbsolute base p = absRel id (base </>) p
 
@@ -740,10 +927,10 @@
 
 -- | Test whether a @'Path' ar fd@ is absolute.
 --
--- >> isAbsolute (asAbsFile "fred")  == True
--- >> isAbsolute (asRelFile "fred")  == False
--- >> isAbsolute (asAbsFile "/fred") == True
--- >> isAbsolute (asRelFile "/fred") == False
+-- >> Posix.isAbsolute (Posix.asAbsFile "fred")
+-- >> Posix.isAbsolute (Posix.asAbsFile "/fred")
+-- >> Windows.isAbsolute (Windows.asAbsFile "\\fred")
+-- >> Windows.isAbsolute (Windows.asAbsFile "c:\\fred")
 isAbsolute :: AbsRelClass ar => Path ar fd -> Bool
 isAbsolute = absRel (const True) (const False)
 
@@ -751,11 +938,17 @@
 --   if interpreted as a 'Path'.
 isAbsoluteString :: String -> Bool
 isAbsoluteString [] = False -- Treat the empty string as relative because it doesn't start with 'pathSeparators'
-isAbsoluteString (x:_) = isPathSeparator x -- Absolute if first char is a path separator
+isAbsoluteString (x:xs) =
+    isPathSeparator x -- Absolute if first char is a path separator
+    ||
+    isWindows && isAlpha x && isPrefixOf ":" xs
 
 -- | Invariant - this should return True iff arg is of type @'Path' Rel _@
 --
 -- > isRelative = not . isAbsolute
+-- >> Posix.isRelative (Posix.asRelFile "fred")
+-- >> Posix.isRelative (Posix.asRelFile "/fred")
+-- >> Windows.isRelative (Windows.asRelFile "fred")
 isRelative :: AbsRelClass ar => Path ar fd -> Bool
 isRelative = not . isAbsolute
 
@@ -769,15 +962,15 @@
 
 -- | Does the given filename have an extension?
 --
--- >> null (takeExtension x) == not (hasAnExtension x)
+-- >> null (Posix.takeExtension x) == not (Posix.hasAnExtension x)
 hasAnExtension :: FilePath ar -> Bool
 hasAnExtension = not . null . snd . splitExtension
 
 -- | Does the given filename have the given extension?
 --
--- >> hasExtension ".hs" "MyCode.hs" == True
--- >> hasExtension ".hs" "MyCode.hs.bak" == False
--- >> hasExtension ".hs" "MyCode.bak.hs" == True
+-- >> Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs")
+-- >> Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.bak.hs")
+-- >> not $ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs.bak")
 hasExtension :: String -> FilePath ar -> Bool
 hasExtension ext = (==ext) . snd . splitExtension
 
@@ -795,7 +988,7 @@
 
 -- | File extension character
 --
--- >> extSeparator == '.'
+-- >> Posix.extSeparator == '.'
 extSeparator :: Char
 extSeparator = '.'
 
@@ -806,14 +999,14 @@
 -- | The character that separates directories. In the case where more than
 --   one character is possible, 'pathSeparator' is the \'ideal\' one.
 --
--- >> isPathSeparator pathSeparator
+-- >> Posix.isPathSeparator Posix.pathSeparator
 pathSeparator :: Char
 pathSeparator | isWindows = '\\'
               | otherwise = '/'
 
 -- | The list of all possible separators.
 --
--- >> pathSeparator `elem` pathSeparators
+-- >> Posix.pathSeparator `elem` Posix.pathSeparators
 pathSeparators :: [Char]
 pathSeparators = return pathSeparator
 
@@ -824,20 +1017,20 @@
 
 -- | Is the character an extension character?
 --
--- >> isExtSeparator a == (a == extSeparator)
+-- >> Posix.isExtSeparator a == (a == Posix.extSeparator)
 isExtSeparator :: Char -> Bool
 isExtSeparator = (== extSeparator)
 
 -- | Rather than using @(== 'pathSeparator')@, use this. Test if something
 --   is a path separator.
 --
--- >> isPathSeparator a == (a `elem` pathSeparators)
+-- >> Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)
 isPathSeparator :: Char -> Bool
 isPathSeparator = flip elem pathSeparators
 
 -- | Is the character a file separator?
 --
--- >> isSearchPathSeparator a == (a == searchPathSeparator)
+-- >> Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)
 isSearchPathSeparator :: Char -> Bool
 isSearchPathSeparator = (== searchPathSeparator)
 
@@ -853,50 +1046,107 @@
 -- | This is a more flexible variant of 'addExtension' / '<.>' which can
 --   work with files or directories
 --
--- >> genericAddExtension "/" "x" == asAbsDir "/.x"
--- >> genericAddExtension "/a" "x" == asAbsDir "/a.x"
--- >> genericAddExtension "" "x" == asRelFile ".x"
--- >> genericAddExtension "" "" == asRelFile ""
-genericAddExtension :: Path ar fd -> String -> Path ar fd
+-- >> Posix.genericAddExtension "/" "x" == Posix.asAbsDir "/.x"
+-- >> Posix.genericAddExtension "/a" "x" == Posix.asAbsDir "/a.x"
+-- >> Posix.genericAddExtension "" "x" == Posix.asRelFile ".x"
+-- >> Posix.genericAddExtension "" "" == Posix.asRelFile ""
+genericAddExtension :: (FileDirClass fd) => Path ar fd -> String -> Path ar fd
 genericAddExtension p "" = p
 genericAddExtension path ext =
-    let suffix =
-            if [extSeparator] `isPrefixOf` ext
-              then ext
-              else extSeparator : ext
-    in  case path of
-            FileDir p (PathComponent pc) ->
-                FileDir p (PathComponent (pc ++ suffix))
-            PathRoot ->
-                FileDir PathRoot (PathComponent suffix)
+    runAddExtension
+        (switchFileDir
+            (AddExtension $
+             \(Path ar pcs (File pc)) ->
+                Path ar pcs $ File $ addExtensionPC pc ext)
+            (AddExtension $
+             \(Path ar pcs0 Dir) ->
+                let pcs = if null pcs0 then [PathComponent ""] else pcs0
+                in  Path ar (mapLast (flip addExtensionPC ext) pcs) Dir))
+        path
 
-genericDropExtension :: Path ar fd -> Path ar fd
+newtype
+    AddExtension ar fd =
+        AddExtension {runAddExtension :: Path ar fd -> Path ar fd}
+
+genericDropExtension :: (FileDirClass fd) => Path ar fd -> Path ar fd
 genericDropExtension = fst . genericSplitExtension
 
-genericDropExtensions :: Path ar fd -> Path ar fd
+genericDropExtensions :: (FileDirClass fd) => Path ar fd -> Path ar fd
 genericDropExtensions = fst . genericSplitExtensions
 
-genericSplitExtension :: Path ar fd -> (Path ar fd, String)
-genericSplitExtension (FileDir p (PathComponent s)) = (FileDir p (PathComponent s1), s2)
+genericSplitExtension ::
+    (FileDirClass fd) => Path ar fd -> (Path ar fd, String)
+genericSplitExtension =
+    runSplitExtension $
+    switchFileDir
+        (SplitExtension $
+         \(Path ar pcs (File pc)) ->
+            first (Path ar pcs . File) $ splitExtensionPC pc)
+        (SplitExtension $
+         \(Path ar pcs Dir) ->
+            first (flip (Path ar) Dir) $
+            mapLastPair
+                (error "genericSplitExtension: empty path")
+                splitExtensionPC pcs)
+
+genericSplitExtensions ::
+    (FileDirClass fd) => Path ar fd -> (Path ar fd, String)
+genericSplitExtensions =
+    runSplitExtension $
+    switchFileDir
+        (SplitExtension $
+         \(Path ar pcs (File pc)) ->
+            first (Path ar pcs . File) $ splitExtensionsPC pc)
+        (SplitExtension $
+         \(Path ar pcs Dir) ->
+            first (flip (Path ar) Dir) $
+            mapLastPair
+                (error "genericSplitExtensions: empty path")
+                splitExtensionsPC pcs)
+
+genericTakeExtension :: (FileDirClass fd) => Path ar fd -> String
+genericTakeExtension = snd . genericSplitExtension
+
+genericTakeExtensions :: (FileDirClass fd) => Path ar fd -> String
+genericTakeExtensions = snd . genericSplitExtension
+
+newtype
+    SplitExtension ar fd =
+        SplitExtension {runSplitExtension :: Path ar fd -> (Path ar fd, String)}
+
+
+-- move to utility-ht
+mapLast :: (a -> a) -> [a] -> [a]
+mapLast f xs = zipWith id (drop 1 $ map (const id) xs ++ [f]) xs
+
+mapLastPair :: b -> (a -> (a,b)) -> [a] -> ([a], b)
+mapLastPair b0 f xs =
+    case reverse xs of
+        [] -> (xs, b0)
+        y:ys ->
+            let (a, b) = f y
+            in  (reverse ys ++ [a], b)
+
+addExtensionPC :: PathComponent -> String -> PathComponent
+addExtensionPC p "" = p
+addExtensionPC (PathComponent pc) ext =
+    PathComponent $ pc ++
+        if [extSeparator] `isPrefixOf` ext
+          then ext
+          else extSeparator : ext
+
+splitExtensionPC :: PathComponent -> (PathComponent, String)
+splitExtensionPC (PathComponent s) = (PathComponent s1, s2)
     where (s1,s2) = fixTrailingDot $ rbreak isExtSeparator s
           fixTrailingDot ("",r2) = (r2,"")
           fixTrailingDot (r1,r2) | [extSeparator] `isSuffixOf` r1 = (init r1, extSeparator:r2)
                                  | otherwise = (r1,r2)
           swap (x,y) = (y,x)
           rbreak q = (reverse *** reverse) . swap . break q . reverse
-genericSplitExtension p = (p,"")
 
-genericSplitExtensions :: Path ar fd -> (Path ar fd, String)
-genericSplitExtensions (FileDir p (PathComponent s)) = (FileDir p (PathComponent s1), s2)
-    where (s1,s2) = break isExtSeparator s
-genericSplitExtensions p = (p,"")
-
-genericTakeExtension :: Path ar fd -> String
-genericTakeExtension = snd . genericSplitExtension
-
-genericTakeExtensions :: Path ar fd -> String
-genericTakeExtensions = snd . genericSplitExtension
-
+splitExtensionsPC :: PathComponent -> (PathComponent, String)
+splitExtensionsPC (PathComponent s) =
+    first PathComponent $ break isExtSeparator s
 
 ------------------------------------------------------------------------
 -- QuickCheck
@@ -937,22 +1187,25 @@
     arbitrary = oneof [qcFileComponent, qcDirComponent]
 
 
-qcGenPath :: Gen PathComponent -> Gen (Path ar fd)
+qcGenPath ::
+    (AbsRelClass ar, FileDirClass fd) =>
+    Gen PathComponent -> Gen (Path ar fd)
 qcGenPath qcLastComponent = do
+    ar <- switchAbsRel (fmap (Abs . (:":")) $ QC.choose ('a', 'z')) (return Rel)
     pcs <- QC.listOf qcDirComponent
     pc <- qcLastComponent
-    return $ mkPathFromComponents (pcs ++ [pc])
+    return $ mkPathFromComponents ar (pcs ++ [pc])
 
-qcFilePath :: Gen (FilePath ar)
+qcFilePath :: (AbsRelClass ar) => Gen (FilePath ar)
 qcFilePath = qcGenPath qcFileComponent
 
-qcDirPath :: Gen (DirPath ar)
+qcDirPath :: (AbsRelClass ar) => Gen (DirPath ar)
 qcDirPath = qcGenPath qcDirComponent
 
-newtype PathGen ar fd = PathGen {runPathGen :: Gen (Path ar fd)}
-
 qcPath :: (AbsRelClass ar, FileDirClass fd) => Gen (Path ar fd)
-qcPath = runPathGen $ switchFileDir (PathGen qcFilePath) (PathGen qcDirPath)
+qcPath =
+    getFunctorPath $
+    switchFileDir (FunctorPath qcFilePath) (FunctorPath qcDirPath)
 
 instance (AbsRelClass ar, FileDirClass fd) => Arbitrary (Path ar fd) where
     arbitrary = qcPath
diff --git a/src/System/Path/Posix.hs b/src/System/Path/Posix.hs
--- a/src/System/Path/Posix.hs
+++ b/src/System/Path/Posix.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE EmptyDataDecls #-}
 {-# LANGUAGE CPP #-}
 #define MODULE_NAME     Posix
 #define IS_WINDOWS      False
diff --git a/src/System/Path/Windows.hs b/src/System/Path/Windows.hs
--- a/src/System/Path/Windows.hs
+++ b/src/System/Path/Windows.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE EmptyDataDecls #-}
 {-# LANGUAGE CPP #-}
 #define MODULE_NAME     Windows
 #define IS_WINDOWS      True
diff --git a/test/TestResult.hs b/test/TestResult.hs
--- a/test/TestResult.hs
+++ b/test/TestResult.hs
@@ -2,214 +2,390 @@
 {-# LANGUAGE OverloadedStrings #-}
 module TestResult (results) where
 
-import System.Path.Posix as Path
+import qualified System.Path.Posix as Posix
+import qualified System.Path.Windows as Windows
+import System.Path ((</>), (<.>))
 import Data.Char (toLower)
 
 
-results :: Char -> Path.FilePath ar -> [(String, Bool)]
+results :: (Posix.AbsRelClass ar) => Char -> Posix.FilePath ar -> [(String, Bool)]
 results a x =
-  ("pathMap (map toLower) \"/tmp/Reports/SpreadSheets\" == \"/tmp/reports/spreadsheets\"",
-    pathMap (map toLower) "/tmp/Reports/SpreadSheets" == "/tmp/reports/spreadsheets") :
-  ("show (rootDir </> \"bla\" </> \"blub\") == \"rootDir </> \\\"bla\\\" </> \\\"blub\\\"\"",
-    show (rootDir </> "bla" </> "blub") == "rootDir </> \"bla\" </> \"blub\"") :
-  ("show (Just (rootDir </> \"bla\" </> \"blub\")) == \"Just (rootDir </> \\\"bla\\\" </> \\\"blub\\\")\"",
-    show (Just (rootDir </> "bla" </> "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")") :
-  ("show (currentDir </> \"bla\" </> \"blub\") == \"currentDir </> \\\"bla\\\" </> \\\"blub\\\"\"",
-    show (currentDir </> "bla" </> "blub") == "currentDir </> \"bla\" </> \"blub\"") :
-  ("show (Just (currentDir </> \"bla\" </> \"blub\")) == \"Just (currentDir </> \\\"bla\\\" </> \\\"blub\\\")\"",
-    show (Just (currentDir </> "bla" </> "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")") :
-  ("read (show (rootDir </> \"bla\" </> \"blub\")) == rootDir </> \"bla\" </> \"blub\"",
-    read (show (rootDir </> "bla" </> "blub")) == rootDir </> "bla" </> "blub") :
-  ("read (show (Just (rootDir </> \"bla\" </> \"blub\"))) == Just (rootDir </> \"bla\" </> \"blub\")",
-    read (show (Just (rootDir </> "bla" </> "blub"))) == Just (rootDir </> "bla" </> "blub")) :
-  ("read (show (currentDir </> \"bla\" </> \"blub\")) == currentDir </> \"bla\" </> \"blub\"",
-    read (show (currentDir </> "bla" </> "blub")) == currentDir </> "bla" </> "blub") :
-  ("read (show (Just (currentDir </> \"bla\" </> \"blub\"))) == Just (currentDir </> \"bla\" </> \"blub\")",
-    read (show (Just (currentDir </> "bla" </> "blub"))) == Just (currentDir </> "bla" </> "blub")) :
-  ("asPath \"/tmp\" == \"/tmp\"",
-    asPath "/tmp" == "/tmp") :
-  ("asPath \"file.txt\" == \"file.txt\"",
-    asPath "file.txt" == "file.txt") :
-  ("isAbsolute (asPath \"/tmp\" :: AbsDir) == True",
-    isAbsolute (asPath "/tmp" :: AbsDir) == True) :
-  ("isAbsolute (asPath \"/tmp\" :: RelDir) == False",
-    isAbsolute (asPath "/tmp" :: RelDir) == False) :
-  ("getPathString (asPath \"/tmp\" :: AbsDir) == \"/tmp\"",
-    getPathString (asPath "/tmp" :: AbsDir) == "/tmp") :
-  ("getPathString (asPath \"/tmp\" :: RelDir) == \"tmp\"",
-    getPathString (asPath "/tmp" :: RelDir) == "tmp") :
-  ("getPathString (asRelFile \"file.txt\") == \"file.txt\"",
-    getPathString (asRelFile "file.txt") == "file.txt") :
-  ("getPathString (asRelFile \"/file.txt\") == \"file.txt\"",
-    getPathString (asRelFile "/file.txt") == "file.txt") :
-  ("getPathString (asRelFile \"tmp\") == \"tmp\"",
-    getPathString (asRelFile "tmp") == "tmp") :
-  ("getPathString (asRelFile \"/tmp\") == \"tmp\"",
-    getPathString (asRelFile "/tmp") == "tmp") :
-  ("getPathString (asRelDir \".\") == \".\"",
-    getPathString (asRelDir ".") == ".") :
-  ("getPathString (asRelDir \"file.txt\") == \"file.txt\"",
-    getPathString (asRelDir "file.txt") == "file.txt") :
-  ("getPathString (asRelDir \"/file.txt\") == \"file.txt\"",
-    getPathString (asRelDir "/file.txt") == "file.txt") :
-  ("getPathString (asRelDir \"tmp\") == \"tmp\"",
-    getPathString (asRelDir "tmp") == "tmp") :
-  ("getPathString (asRelDir \"/tmp\") == \"tmp\"",
-    getPathString (asRelDir "/tmp") == "tmp") :
-  ("getPathString (asAbsFile \"file.txt\") == \"/file.txt\"",
-    getPathString (asAbsFile "file.txt") == "/file.txt") :
-  ("getPathString (asAbsFile \"/file.txt\") == \"/file.txt\"",
-    getPathString (asAbsFile "/file.txt") == "/file.txt") :
-  ("getPathString (asAbsFile \"tmp\") == \"/tmp\"",
-    getPathString (asAbsFile "tmp") == "/tmp") :
-  ("getPathString (asAbsFile \"/tmp\") == \"/tmp\"",
-    getPathString (asAbsFile "/tmp") == "/tmp") :
-  ("getPathString (asAbsDir \"file.txt\") == \"/file.txt\"",
-    getPathString (asAbsDir "file.txt") == "/file.txt") :
-  ("getPathString (asAbsDir \"/file.txt\") == \"/file.txt\"",
-    getPathString (asAbsDir "/file.txt") == "/file.txt") :
-  ("getPathString (asAbsDir \"tmp\") == \"/tmp\"",
-    getPathString (asAbsDir "tmp") == "/tmp") :
-  ("getPathString (asAbsDir \"/tmp\") == \"/tmp\"",
-    getPathString (asAbsDir "/tmp") == "/tmp") :
-  ("mkPathAbsOrRel \"/tmp\" == Left (asAbsDir \"/tmp\")",
-    mkPathAbsOrRel "/tmp" == Left (asAbsDir "/tmp")) :
-  ("mkPathAbsOrRel  \"tmp\" == Right (asRelDir \"tmp\")",
-    mkPathAbsOrRel  "tmp" == Right (asRelDir "tmp")) :
-  ("mkAbsPath \"/tmp\" \"foo.txt\" == \"/tmp/foo.txt\"",
-    mkAbsPath "/tmp" "foo.txt" == "/tmp/foo.txt") :
-  ("mkAbsPath \"/tmp\" \"/etc/foo.txt\" == \"/etc/foo.txt\"",
-    mkAbsPath "/tmp" "/etc/foo.txt" == "/etc/foo.txt") :
-  ("addExtension \"file.txt\" \"bib\" == \"file.txt.bib\"",
-    addExtension "file.txt" "bib" == "file.txt.bib") :
-  ("addExtension \"file.\" \".bib\" == \"file..bib\"",
-    addExtension "file." ".bib" == "file..bib") :
-  ("addExtension \"file\" \".bib\" == \"file.bib\"",
-    addExtension "file" ".bib" == "file.bib") :
-  ("addExtension \"\" \"bib\" == \".bib\"",
-    addExtension "" "bib" == ".bib") :
-  ("addExtension \"\" \".bib\" == \".bib\"",
-    addExtension "" ".bib" == ".bib") :
-  ("takeFileName (addExtension \"\" \"ext\") == \".ext\"",
-    takeFileName (addExtension "" "ext") == ".ext") :
-  ("dropExtension x == fst (splitExtension x)",
-    dropExtension x == fst (splitExtension x)) :
-  ("not $ hasAnExtension (dropExtensions x)",
-    not $ hasAnExtension (dropExtensions x)) :
-  ("replaceExtension \"file.txt\" \".bob\" == \"file.bob\"",
-    replaceExtension "file.txt" ".bob" == "file.bob") :
-  ("replaceExtension \"file.txt\" \"bob\" == \"file.bob\"",
-    replaceExtension "file.txt" "bob" == "file.bob") :
-  ("replaceExtension \"file\" \".bob\" == \"file.bob\"",
-    replaceExtension "file" ".bob" == "file.bob") :
-  ("replaceExtension \"file.txt\" \"\" == \"file\"",
-    replaceExtension "file.txt" "" == "file") :
-  ("replaceExtension \"file.fred.bob\" \"txt\" == \"file.fred.txt\"",
-    replaceExtension "file.fred.bob" "txt" == "file.fred.txt") :
-  ("uncurry (<.>) (splitExtension x) == x",
-    uncurry (<.>) (splitExtension x) == x) :
-  ("uncurry addExtension (splitExtension x) == x",
-    uncurry addExtension (splitExtension x) == x) :
-  ("splitExtension \"file.txt\" == (\"file\",\".txt\")",
-    splitExtension "file.txt" == ("file",".txt")) :
-  ("splitExtension \"file\" == (\"file\",\"\")",
-    splitExtension "file" == ("file","")) :
-  ("splitExtension \"file/file.txt\" == (\"file/file\",\".txt\")",
-    splitExtension "file/file.txt" == ("file/file",".txt")) :
-  ("splitExtension \"file.txt/boris\" == (\"file.txt/boris\",\"\")",
-    splitExtension "file.txt/boris" == ("file.txt/boris","")) :
-  ("splitExtension \"file.txt/boris.ext\" == (\"file.txt/boris\",\".ext\")",
-    splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")) :
-  ("splitExtension \"file/path.txt.bob.fred\" == (\"file/path.txt.bob\",\".fred\")",
-    splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")) :
-  ("splitExtensions \"file.tar.gz\" == (\"file\",\".tar.gz\")",
-    splitExtensions "file.tar.gz" == ("file",".tar.gz")) :
-  ("takeBaseName \"/tmp/somedir/myfile.txt\" == \"myfile\"",
-    takeBaseName "/tmp/somedir/myfile.txt" == "myfile") :
-  ("takeBaseName \"./myfile.txt\" == \"myfile\"",
-    takeBaseName "./myfile.txt" == "myfile") :
-  ("takeBaseName \"myfile.txt\" == \"myfile\"",
-    takeBaseName "myfile.txt" == "myfile") :
-  ("takeExtension x == snd (splitExtension x)",
-    takeExtension x == snd (splitExtension x)) :
-  ("takeExtension (addExtension x \"ext\") == \".ext\"",
-    takeExtension (addExtension x "ext") == ".ext") :
-  ("takeExtension (replaceExtension x \"ext\") == \".ext\"",
-    takeExtension (replaceExtension x "ext") == ".ext") :
-  ("takeExtensions \"file.tar.gz\" == \".tar.gz\"",
-    takeExtensions "file.tar.gz" == ".tar.gz") :
-  ("takeFileName \"/tmp/somedir/myfile.txt\" == \"myfile.txt\"",
-    takeFileName "/tmp/somedir/myfile.txt" == "myfile.txt") :
-  ("takeFileName \"./myfile.txt\" == \"myfile.txt\"",
-    takeFileName "./myfile.txt" == "myfile.txt") :
-  ("takeFileName \"myfile.txt\" == \"myfile.txt\"",
-    takeFileName "myfile.txt" == "myfile.txt") :
-  ("equalFilePath \"/tmp/\" \"/tmp\" == True",
-    equalFilePath "/tmp/" "/tmp" == True) :
-  ("equalFilePath \"/tmp\"  \"tmp\"  == False",
-    equalFilePath "/tmp"  "tmp"  == False) :
-  ("joinPath [\"/tmp\",\"someDir\",\"file.txt\"] == \"/tmp/someDir/file.txt\"",
-    joinPath ["/tmp","someDir","file.txt"] == "/tmp/someDir/file.txt") :
-  ("joinPath [\"/tmp\",\"someDir\",\"file.txt\"] == asRelFile \"tmp/someDir/file.txt\"",
-    joinPath ["/tmp","someDir","file.txt"] == asRelFile "tmp/someDir/file.txt") :
-  ("normalise \"/tmp/fred/./jim/./file\" == \"/tmp/fred/jim/file\"",
-    normalise "/tmp/fred/./jim/./file" == "/tmp/fred/jim/file") :
-  ("splitPath (asAbsDir \"/tmp/someDir/mydir.dir\") == ([\"tmp\",\"someDir\",\"mydir.dir\"], Nothing)",
-    splitPath (asAbsDir "/tmp/someDir/mydir.dir") == (["tmp","someDir","mydir.dir"], Nothing)) :
-  ("splitPath (asAbsFile \"/tmp/someDir/myfile.txt\") == ([\"tmp\",\"someDir\"], Just \"myfile.txt\")",
-    splitPath (asAbsFile "/tmp/someDir/myfile.txt") == (["tmp","someDir"], Just "myfile.txt")) :
-  ("makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/file.txt\" == asRelFile \"anotherdir/file.txt\"",
-    makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == asRelFile "anotherdir/file.txt") :
-  ("makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/dir\" == asRelDir \"anotherdir/dir\"",
-    makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == asRelDir "anotherdir/dir") :
-  ("makeAbsolute \"/tmp\" \"file.txt\"      == asAbsFile \"/tmp/file.txt\"",
-    makeAbsolute "/tmp" "file.txt"      == asAbsFile "/tmp/file.txt") :
-  ("makeAbsolute \"/tmp\" \"adir/file.txt\" == asAbsFile \"/tmp/adir/file.txt\"",
-    makeAbsolute "/tmp" "adir/file.txt" == asAbsFile "/tmp/adir/file.txt") :
-  ("makeAbsolute \"/tmp\" \"adir/dir\"      == asAbsDir \"/tmp/adir/dir\"",
-    makeAbsolute "/tmp" "adir/dir"      == asAbsDir "/tmp/adir/dir") :
-  ("genericMakeAbsolute \"/tmp\" (asRelFile \"file.txt\")       == \"/tmp/file.txt\"",
-    genericMakeAbsolute "/tmp" (asRelFile "file.txt")       == "/tmp/file.txt") :
-  ("genericMakeAbsolute \"/tmp\" (asRelFile \"adir/file.txt\")  == \"/tmp/adir/file.txt\"",
-    genericMakeAbsolute "/tmp" (asRelFile "adir/file.txt")  == "/tmp/adir/file.txt") :
-  ("genericMakeAbsolute \"/tmp\" (asAbsFile \"adir/file.txt\")  == \"/adir/file.txt\"",
-    genericMakeAbsolute "/tmp" (asAbsFile "adir/file.txt")  == "/adir/file.txt") :
-  ("genericMakeAbsolute \"/tmp\" (asAbsFile \"/adir/file.txt\") == \"/adir/file.txt\"",
-    genericMakeAbsolute "/tmp" (asAbsFile "/adir/file.txt") == "/adir/file.txt") :
-  ("isAbsolute (asAbsFile \"fred\")  == True",
-    isAbsolute (asAbsFile "fred")  == True) :
-  ("isAbsolute (asRelFile \"fred\")  == False",
-    isAbsolute (asRelFile "fred")  == False) :
-  ("isAbsolute (asAbsFile \"/fred\") == True",
-    isAbsolute (asAbsFile "/fred") == True) :
-  ("isAbsolute (asRelFile \"/fred\") == False",
-    isAbsolute (asRelFile "/fred") == False) :
-  ("null (takeExtension x) == not (hasAnExtension x)",
-    null (takeExtension x) == not (hasAnExtension x)) :
-  ("hasExtension \".hs\" \"MyCode.hs\" == True",
-    hasExtension ".hs" "MyCode.hs" == True) :
-  ("hasExtension \".hs\" \"MyCode.hs.bak\" == False",
-    hasExtension ".hs" "MyCode.hs.bak" == False) :
-  ("hasExtension \".hs\" \"MyCode.bak.hs\" == True",
-    hasExtension ".hs" "MyCode.bak.hs" == True) :
-  ("extSeparator == '.'",
-    extSeparator == '.') :
-  ("isPathSeparator pathSeparator",
-    isPathSeparator pathSeparator) :
-  ("pathSeparator `elem` pathSeparators",
-    pathSeparator `elem` pathSeparators) :
-  ("isExtSeparator a == (a == extSeparator)",
-    isExtSeparator a == (a == extSeparator)) :
-  ("isPathSeparator a == (a `elem` pathSeparators)",
-    isPathSeparator a == (a `elem` pathSeparators)) :
-  ("isSearchPathSeparator a == (a == searchPathSeparator)",
-    isSearchPathSeparator a == (a == searchPathSeparator)) :
-  ("genericAddExtension \"/\" \"x\" == asAbsDir \"/.x\"",
-    genericAddExtension "/" "x" == asAbsDir "/.x") :
-  ("genericAddExtension \"/a\" \"x\" == asAbsDir \"/a.x\"",
-    genericAddExtension "/a" "x" == asAbsDir "/a.x") :
-  ("genericAddExtension \"\" \"x\" == asRelFile \".x\"",
-    genericAddExtension "" "x" == asRelFile ".x") :
-  ("genericAddExtension \"\" \"\" == asRelFile \"\"",
-    genericAddExtension "" "" == asRelFile "") :
+  {-# LINE 255 "src/System/Path/Internal.hs" #-}
+  ("Posix.pathMap (map toLower) \"/tmp/Reports/SpreadSheets\" == Posix.asAbsDir \"/tmp/reports/spreadsheets\"",
+      Posix.pathMap (map toLower) "/tmp/Reports/SpreadSheets" == Posix.asAbsDir "/tmp/reports/spreadsheets") :
+  {-# LINE 322 "src/System/Path/Internal.hs" #-}
+  ("show (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\") == \"rootDir </> \\\"bla\\\" </> \\\"blub\\\"\"",
+      show (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") == "rootDir </> \"bla\" </> \"blub\"") :
+  {-# LINE 323 "src/System/Path/Internal.hs" #-}
+  ("show (Just (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\")) == \"Just (rootDir </> \\\"bla\\\" </> \\\"blub\\\")\"",
+      show (Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub")) == "Just (rootDir </> \"bla\" </> \"blub\")") :
+  {-# LINE 324 "src/System/Path/Internal.hs" #-}
+  ("show (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\") == \"currentDir </> \\\"bla\\\" </> \\\"blub\\\"\"",
+      show (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") == "currentDir </> \"bla\" </> \"blub\"") :
+  {-# LINE 325 "src/System/Path/Internal.hs" #-}
+  ("show (Just (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\")) == \"Just (currentDir </> \\\"bla\\\" </> \\\"blub\\\")\"",
+      show (Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub")) == "Just (currentDir </> \"bla\" </> \"blub\")") :
+  {-# LINE 326 "src/System/Path/Internal.hs" #-}
+  ("show (Windows.asAbsDir \"c:\" Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\") == \"asAbsDir \\\"c:\\\" </> \\\"bla\\\" </> \\\"blub\\\"\"",
+      show (Windows.asAbsDir "c:" Windows.</> "bla" Windows.</> Windows.asRelFile "blub") == "asAbsDir \"c:\" </> \"bla\" </> \"blub\"") :
+  {-# LINE 327 "src/System/Path/Internal.hs" #-}
+  ("show (Just (Windows.asAbsDir \"c:\\\\\" Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\")) == \"Just (asAbsDir \\\"c:\\\" </> \\\"bla\\\" </> \\\"blub\\\")\"",
+      show (Just (Windows.asAbsDir "c:\\" Windows.</> "bla" Windows.</> Windows.asRelFile "blub")) == "Just (asAbsDir \"c:\" </> \"bla\" </> \"blub\")") :
+  {-# LINE 348 "src/System/Path/Internal.hs" #-}
+  ("let path = Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\" in read (show path) == path",
+      let path = Posix.rootDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path) :
+  {-# LINE 349 "src/System/Path/Internal.hs" #-}
+  ("let path = Just (Posix.rootDir </> \"bla\" </> Posix.asRelFile \"blub\") in read (show path) == path",
+      let path = Just (Posix.rootDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path) :
+  {-# LINE 350 "src/System/Path/Internal.hs" #-}
+  ("let path = Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\" in read (show path) == path",
+      let path = Posix.currentDir </> "bla" </> Posix.asRelFile "blub" in read (show path) == path) :
+  {-# LINE 351 "src/System/Path/Internal.hs" #-}
+  ("let path = Just (Posix.currentDir </> \"bla\" </> Posix.asRelFile \"blub\") in read (show path) == path",
+      let path = Just (Posix.currentDir </> "bla" </> Posix.asRelFile "blub") in read (show path) == path) :
+  {-# LINE 352 "src/System/Path/Internal.hs" #-}
+  ("let path = Windows.rootDir Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\" in read (show path) == path",
+      let path = Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub" in read (show path) == path) :
+  {-# LINE 353 "src/System/Path/Internal.hs" #-}
+  ("let path = Just (Windows.rootDir Windows.</> \"bla\" Windows.</> Windows.asRelFile \"blub\") in read (show path) == path",
+      let path = Just (Windows.rootDir Windows.</> "bla" Windows.</> Windows.asRelFile "blub") in read (show path) == path) :
+  {-# LINE 444 "src/System/Path/Internal.hs" #-}
+  ("Posix.asPath \"/tmp\" == Posix.asAbsDir \"/tmp\"",
+      Posix.asPath "/tmp" == Posix.asAbsDir "/tmp") :
+  {-# LINE 445 "src/System/Path/Internal.hs" #-}
+  ("Posix.asPath \"file.txt\" == Posix.asRelFile \"file.txt\"",
+      Posix.asPath "file.txt" == Posix.asRelFile "file.txt") :
+  {-# LINE 446 "src/System/Path/Internal.hs" #-}
+  ("Posix.isAbsolute (Posix.asAbsDir \"/tmp\")",
+      Posix.isAbsolute (Posix.asAbsDir "/tmp")) :
+  {-# LINE 447 "src/System/Path/Internal.hs" #-}
+  ("Posix.isRelative (Posix.asRelDir \"/tmp\")",
+      Posix.isRelative (Posix.asRelDir "/tmp")) :
+  {-# LINE 448 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asPath \"/tmp\" :: Posix.AbsDir) == \"/tmp\"",
+      Posix.getPathString (Posix.asPath "/tmp" :: Posix.AbsDir) == "/tmp") :
+  {-# LINE 449 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asPath \"/tmp\" :: Posix.RelDir) == \"tmp\"",
+      Posix.getPathString (Posix.asPath "/tmp" :: Posix.RelDir) == "tmp") :
+  {-# LINE 450 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asPath \"\\\\tmp\" :: Windows.AbsDir) == \"\\\\tmp\"",
+      Windows.getPathString (Windows.asPath "\\tmp" :: Windows.AbsDir) == "\\tmp") :
+  {-# LINE 451 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asPath \"a:\\\\tmp\" :: Windows.AbsDir) == \"a:\\\\tmp\"",
+      Windows.getPathString (Windows.asPath "a:\\tmp" :: Windows.AbsDir) == "a:\\tmp") :
+  {-# LINE 452 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asPath \"tmp\" :: Windows.RelDir) == \"tmp\"",
+      Windows.getPathString (Windows.asPath "tmp" :: Windows.RelDir) == "tmp") :
+  {-# LINE 465 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelFile \"file.txt\") == \"file.txt\"",
+      Posix.getPathString (Posix.asRelFile "file.txt") == "file.txt") :
+  {-# LINE 466 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelFile \"/file.txt\") == \"file.txt\"",
+      Posix.getPathString (Posix.asRelFile "/file.txt") == "file.txt") :
+  {-# LINE 467 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelFile \"tmp\") == \"tmp\"",
+      Posix.getPathString (Posix.asRelFile "tmp") == "tmp") :
+  {-# LINE 468 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelFile \"/tmp\") == \"tmp\"",
+      Posix.getPathString (Posix.asRelFile "/tmp") == "tmp") :
+  {-# LINE 474 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \".\") == \".\"",
+      Posix.getPathString (Posix.asRelDir ".") == ".") :
+  {-# LINE 475 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \"file.txt\") == \"file.txt\"",
+      Posix.getPathString (Posix.asRelDir "file.txt") == "file.txt") :
+  {-# LINE 476 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \"/file.txt\") == \"file.txt\"",
+      Posix.getPathString (Posix.asRelDir "/file.txt") == "file.txt") :
+  {-# LINE 477 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \"tmp\") == \"tmp\"",
+      Posix.getPathString (Posix.asRelDir "tmp") == "tmp") :
+  {-# LINE 478 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \"/tmp\") == \"tmp\"",
+      Posix.getPathString (Posix.asRelDir "/tmp") == "tmp") :
+  {-# LINE 484 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsFile \"file.txt\") == \"/file.txt\"",
+      Posix.getPathString (Posix.asAbsFile "file.txt") == "/file.txt") :
+  {-# LINE 485 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsFile \"/file.txt\") == \"/file.txt\"",
+      Posix.getPathString (Posix.asAbsFile "/file.txt") == "/file.txt") :
+  {-# LINE 486 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsFile \"tmp\") == \"/tmp\"",
+      Posix.getPathString (Posix.asAbsFile "tmp") == "/tmp") :
+  {-# LINE 487 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsFile \"/tmp\") == \"/tmp\"",
+      Posix.getPathString (Posix.asAbsFile "/tmp") == "/tmp") :
+  {-# LINE 493 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"file.txt\") == \"/file.txt\"",
+      Posix.getPathString (Posix.asAbsDir "file.txt") == "/file.txt") :
+  {-# LINE 494 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"/file.txt\") == \"/file.txt\"",
+      Posix.getPathString (Posix.asAbsDir "/file.txt") == "/file.txt") :
+  {-# LINE 495 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"tmp\") == \"/tmp\"",
+      Posix.getPathString (Posix.asAbsDir "tmp") == "/tmp") :
+  {-# LINE 496 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"/tmp\") == \"/tmp\"",
+      Posix.getPathString (Posix.asAbsDir "/tmp") == "/tmp") :
+  {-# LINE 527 "src/System/Path/Internal.hs" #-}
+  ("Posix.mkPathAbsOrRel \"/tmp\" == Left (Posix.asAbsDir \"/tmp\")",
+      Posix.mkPathAbsOrRel "/tmp" == Left (Posix.asAbsDir "/tmp")) :
+  {-# LINE 528 "src/System/Path/Internal.hs" #-}
+  ("Posix.mkPathAbsOrRel  \"tmp\" == Right (Posix.asRelDir \"tmp\")",
+      Posix.mkPathAbsOrRel  "tmp" == Right (Posix.asRelDir "tmp")) :
+  {-# LINE 529 "src/System/Path/Internal.hs" #-}
+  ("Windows.mkPathAbsOrRel \"\\\\tmp\" == Left (Windows.asAbsDir \"\\\\tmp\")",
+      Windows.mkPathAbsOrRel "\\tmp" == Left (Windows.asAbsDir "\\tmp")) :
+  {-# LINE 530 "src/System/Path/Internal.hs" #-}
+  ("Windows.mkPathAbsOrRel \"d:\\\\tmp\" == Left (Windows.asAbsDir \"d:\\\\tmp\")",
+      Windows.mkPathAbsOrRel "d:\\tmp" == Left (Windows.asAbsDir "d:\\tmp")) :
+  {-# LINE 531 "src/System/Path/Internal.hs" #-}
+  ("Windows.mkPathAbsOrRel \"tmp\" == Right (Windows.asRelDir \"tmp\")",
+      Windows.mkPathAbsOrRel "tmp" == Right (Windows.asRelDir "tmp")) :
+  {-# LINE 556 "src/System/Path/Internal.hs" #-}
+  ("Posix.mkAbsPath \"/tmp\" \"foo.txt\" == Posix.asAbsFile \"/tmp/foo.txt\"",
+      Posix.mkAbsPath "/tmp" "foo.txt" == Posix.asAbsFile "/tmp/foo.txt") :
+  {-# LINE 557 "src/System/Path/Internal.hs" #-}
+  ("Posix.mkAbsPath \"/tmp\" \"/etc/foo.txt\" == Posix.asAbsFile \"/etc/foo.txt\"",
+      Posix.mkAbsPath "/tmp" "/etc/foo.txt" == Posix.asAbsFile "/etc/foo.txt") :
+  {-# LINE 649 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"/tmp\" </> Posix.asRelFile \"file.txt\") == \"/tmp/file.txt\"",
+      Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelFile "file.txt") == "/tmp/file.txt") :
+  {-# LINE 650 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asAbsDir \"/tmp\" </> Posix.asRelDir \"dir\" </> Posix.asRelFile \"file.txt\") == \"/tmp/dir/file.txt\"",
+      Posix.getPathString (Posix.asAbsDir "/tmp" </> Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "/tmp/dir/file.txt") :
+  {-# LINE 651 "src/System/Path/Internal.hs" #-}
+  ("Posix.getPathString (Posix.asRelDir \"dir\" </> Posix.asRelFile \"file.txt\") == \"dir/file.txt\"",
+      Posix.getPathString (Posix.asRelDir "dir" </> Posix.asRelFile "file.txt") == "dir/file.txt") :
+  {-# LINE 652 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asAbsDir \"\\\\tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"\\\\tmp\\\\file.txt\"",
+      Windows.getPathString (Windows.asAbsDir "\\tmp" Windows.</> Windows.asRelFile "file.txt") == "\\tmp\\file.txt") :
+  {-# LINE 653 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asAbsDir \"c:\\\\tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"c:\\\\tmp\\\\file.txt\"",
+      Windows.getPathString (Windows.asAbsDir "c:\\tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt") :
+  {-# LINE 654 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asAbsDir \"c:\" Windows.</> Windows.asRelDir \"tmp\" Windows.</> Windows.asRelFile \"file.txt\") == \"c:\\\\tmp\\\\file.txt\"",
+      Windows.getPathString (Windows.asAbsDir "c:" Windows.</> Windows.asRelDir "tmp" Windows.</> Windows.asRelFile "file.txt") == "c:\\tmp\\file.txt") :
+  {-# LINE 655 "src/System/Path/Internal.hs" #-}
+  ("Windows.getPathString (Windows.asRelDir \"dir\" Windows.</> Windows.asRelFile \"file.txt\") == \"dir\\\\file.txt\"",
+      Windows.getPathString (Windows.asRelDir "dir" Windows.</> Windows.asRelFile "file.txt") == "dir\\file.txt") :
+  {-# LINE 673 "src/System/Path/Internal.hs" #-}
+  ("Posix.addExtension (Posix.asRelFile \"file.txt\") \"bib\" == \"file.txt.bib\"",
+      Posix.addExtension (Posix.asRelFile "file.txt") "bib" == "file.txt.bib") :
+  {-# LINE 674 "src/System/Path/Internal.hs" #-}
+  ("Posix.addExtension (Posix.asRelFile \"file.\") \".bib\" == \"file..bib\"",
+      Posix.addExtension (Posix.asRelFile "file.") ".bib" == "file..bib") :
+  {-# LINE 675 "src/System/Path/Internal.hs" #-}
+  ("Posix.addExtension (Posix.asRelFile \"file\") \".bib\" == \"file.bib\"",
+      Posix.addExtension (Posix.asRelFile "file") ".bib" == "file.bib") :
+  {-# LINE 676 "src/System/Path/Internal.hs" #-}
+  ("Posix.addExtension (Posix.asRelFile \"\") \"bib\" == \".bib\"",
+      Posix.addExtension (Posix.asRelFile "") "bib" == ".bib") :
+  {-# LINE 677 "src/System/Path/Internal.hs" #-}
+  ("Posix.addExtension (Posix.asRelFile \"\") \".bib\" == \".bib\"",
+      Posix.addExtension (Posix.asRelFile "") ".bib" == ".bib") :
+  {-# LINE 678 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeFileName (Posix.addExtension (Posix.asRelFile \"\") \"ext\") == \".ext\"",
+      Posix.takeFileName (Posix.addExtension (Posix.asRelFile "") "ext") == ".ext") :
+  {-# LINE 690 "src/System/Path/Internal.hs" #-}
+  ("Posix.dropExtension x == fst (Posix.splitExtension x)",
+      Posix.dropExtension x == fst (Posix.splitExtension x)) :
+  {-# LINE 696 "src/System/Path/Internal.hs" #-}
+  ("not $ Posix.hasAnExtension (Posix.dropExtensions x)",
+      not $ Posix.hasAnExtension (Posix.dropExtensions x)) :
+  {-# LINE 707 "src/System/Path/Internal.hs" #-}
+  ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \".bob\" == \"file.bob\"",
+      Posix.replaceExtension (Posix.asRelFile "file.txt") ".bob" == "file.bob") :
+  {-# LINE 708 "src/System/Path/Internal.hs" #-}
+  ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \"bob\" == \"file.bob\"",
+      Posix.replaceExtension (Posix.asRelFile "file.txt") "bob" == "file.bob") :
+  {-# LINE 709 "src/System/Path/Internal.hs" #-}
+  ("Posix.replaceExtension (Posix.asRelFile \"file\") \".bob\" == \"file.bob\"",
+      Posix.replaceExtension (Posix.asRelFile "file") ".bob" == "file.bob") :
+  {-# LINE 710 "src/System/Path/Internal.hs" #-}
+  ("Posix.replaceExtension (Posix.asRelFile \"file.txt\") \"\" == \"file\"",
+      Posix.replaceExtension (Posix.asRelFile "file.txt") "" == "file") :
+  {-# LINE 711 "src/System/Path/Internal.hs" #-}
+  ("Posix.replaceExtension (Posix.asRelFile \"file.fred.bob\") \"txt\" == \"file.fred.txt\"",
+      Posix.replaceExtension (Posix.asRelFile "file.fred.bob") "txt" == "file.fred.txt") :
+  {-# LINE 729 "src/System/Path/Internal.hs" #-}
+  ("uncurry (<.>) (Posix.splitExtension x) == x",
+      uncurry (<.>) (Posix.splitExtension x) == x) :
+  {-# LINE 730 "src/System/Path/Internal.hs" #-}
+  ("uncurry Posix.addExtension (Posix.splitExtension x) == x",
+      uncurry Posix.addExtension (Posix.splitExtension x) == x) :
+  {-# LINE 731 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file.txt\") == (\"file\",\".txt\")",
+      Posix.splitExtension (Posix.asRelFile "file.txt") == ("file",".txt")) :
+  {-# LINE 732 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file\") == (\"file\",\"\")",
+      Posix.splitExtension (Posix.asRelFile "file") == ("file","")) :
+  {-# LINE 733 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file/file.txt\") == (\"file/file\",\".txt\")",
+      Posix.splitExtension (Posix.asRelFile "file/file.txt") == ("file/file",".txt")) :
+  {-# LINE 734 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file.txt/boris\") == (\"file.txt/boris\",\"\")",
+      Posix.splitExtension (Posix.asRelFile "file.txt/boris") == ("file.txt/boris","")) :
+  {-# LINE 735 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file.txt/boris.ext\") == (\"file.txt/boris\",\".ext\")",
+      Posix.splitExtension (Posix.asRelFile "file.txt/boris.ext") == ("file.txt/boris",".ext")) :
+  {-# LINE 736 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtension (Posix.asRelFile \"file/path.txt.bob.fred\") == (\"file/path.txt.bob\",\".fred\")",
+      Posix.splitExtension (Posix.asRelFile "file/path.txt.bob.fred") == ("file/path.txt.bob",".fred")) :
+  {-# LINE 743 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitExtensions (Posix.asRelFile \"file.tar.gz\") == (\"file\",\".tar.gz\")",
+      Posix.splitExtensions (Posix.asRelFile "file.tar.gz") == ("file",".tar.gz")) :
+  {-# LINE 760 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeBaseName (Posix.asAbsFile \"/tmp/somedir/myfile.txt\") == \"myfile\"",
+      Posix.takeBaseName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile") :
+  {-# LINE 761 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeBaseName (Posix.asRelFile \"./myfile.txt\") == \"myfile\"",
+      Posix.takeBaseName (Posix.asRelFile "./myfile.txt") == "myfile") :
+  {-# LINE 762 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeBaseName (Posix.asRelFile \"myfile.txt\") == \"myfile\"",
+      Posix.takeBaseName (Posix.asRelFile "myfile.txt") == "myfile") :
+  {-# LINE 771 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeExtension x == snd (Posix.splitExtension x)",
+      Posix.takeExtension x == snd (Posix.splitExtension x)) :
+  {-# LINE 772 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeExtension (Posix.addExtension x \"ext\") == \".ext\"",
+      Posix.takeExtension (Posix.addExtension x "ext") == ".ext") :
+  {-# LINE 773 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeExtension (Posix.replaceExtension x \"ext\") == \".ext\"",
+      Posix.takeExtension (Posix.replaceExtension x "ext") == ".ext") :
+  {-# LINE 779 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeExtensions (Posix.asRelFile \"file.tar.gz\") == \".tar.gz\"",
+      Posix.takeExtensions (Posix.asRelFile "file.tar.gz") == ".tar.gz") :
+  {-# LINE 785 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeFileName (Posix.asAbsFile \"/tmp/somedir/myfile.txt\") == \"myfile.txt\"",
+      Posix.takeFileName (Posix.asAbsFile "/tmp/somedir/myfile.txt") == "myfile.txt") :
+  {-# LINE 786 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeFileName (Posix.asRelFile \"./myfile.txt\") == \"myfile.txt\"",
+      Posix.takeFileName (Posix.asRelFile "./myfile.txt") == "myfile.txt") :
+  {-# LINE 787 "src/System/Path/Internal.hs" #-}
+  ("Posix.takeFileName (Posix.asRelFile \"myfile.txt\") == \"myfile.txt\"",
+      Posix.takeFileName (Posix.asRelFile "myfile.txt") == "myfile.txt") :
+  {-# LINE 800 "src/System/Path/Internal.hs" #-}
+  ("      Posix.equalFilePath \"/tmp/\" \"/tmp\"",
+            Posix.equalFilePath "/tmp/" "/tmp") :
+  {-# LINE 801 "src/System/Path/Internal.hs" #-}
+  ("not $ Posix.equalFilePath \"/tmp\" \"tmp\"",
+      not $ Posix.equalFilePath "/tmp" "tmp") :
+  {-# LINE 802 "src/System/Path/Internal.hs" #-}
+  ("      Windows.equalFilePath \"file\" \"File\"",
+            Windows.equalFilePath "file" "File") :
+  {-# LINE 803 "src/System/Path/Internal.hs" #-}
+  ("not $ Windows.equalFilePath \"file\" \"dir\"",
+      not $ Windows.equalFilePath "file" "dir") :
+  {-# LINE 817 "src/System/Path/Internal.hs" #-}
+  ("Posix.joinPath [\"tmp\",\"someDir\",\"dir\"] == Posix.asRelDir \"tmp/someDir/dir\"",
+      Posix.joinPath ["tmp","someDir","dir"] == Posix.asRelDir "tmp/someDir/dir") :
+  {-# LINE 818 "src/System/Path/Internal.hs" #-}
+  ("Posix.joinPath [\"tmp\",\"someDir\",\"file.txt\"] == Posix.asRelFile \"tmp/someDir/file.txt\"",
+      Posix.joinPath ["tmp","someDir","file.txt"] == Posix.asRelFile "tmp/someDir/file.txt") :
+  {-# LINE 824 "src/System/Path/Internal.hs" #-}
+  ("Posix.normalise \"/tmp/fred/./jim/./file\" == Posix.asAbsFile \"/tmp/fred/jim/file\"",
+      Posix.normalise "/tmp/fred/./jim/./file" == Posix.asAbsFile "/tmp/fred/jim/file") :
+  {-# LINE 831 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitPath (Posix.asAbsDir \"/tmp/someDir/mydir.dir\") == (True, [\"tmp\",\"someDir\",\"mydir.dir\"], Nothing)",
+      Posix.splitPath (Posix.asAbsDir "/tmp/someDir/mydir.dir") == (True, ["tmp","someDir","mydir.dir"], Nothing)) :
+  {-# LINE 832 "src/System/Path/Internal.hs" #-}
+  ("Posix.splitPath (Posix.asAbsFile \"/tmp/someDir/myfile.txt\") == (True, [\"tmp\",\"someDir\"], Just \"myfile.txt\")",
+      Posix.splitPath (Posix.asAbsFile "/tmp/someDir/myfile.txt") == (True, ["tmp","someDir"], Just "myfile.txt")) :
+  {-# LINE 851 "src/System/Path/Internal.hs" #-}
+  ("Posix.makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/file.txt\" == Posix.asRelFile \"anotherdir/file.txt\"",
+      Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/file.txt" == Posix.asRelFile "anotherdir/file.txt") :
+  {-# LINE 852 "src/System/Path/Internal.hs" #-}
+  ("Posix.makeRelative \"/tmp/somedir\" \"/tmp/somedir/anotherdir/dir\" == Posix.asRelDir \"anotherdir/dir\"",
+      Posix.makeRelative "/tmp/somedir" "/tmp/somedir/anotherdir/dir" == Posix.asRelDir "anotherdir/dir") :
+  {-# LINE 853 "src/System/Path/Internal.hs" #-}
+  ("Windows.makeRelative \"c:\\\\tmp\\\\somedir\" \"c:\\\\Tmp\\\\SomeDir\\\\AnotherDir\\\\File.txt\" == Windows.asRelFile \"AnotherDir\\\\File.txt\"",
+      Windows.makeRelative "c:\\tmp\\somedir" "c:\\Tmp\\SomeDir\\AnotherDir\\File.txt" == Windows.asRelFile "AnotherDir\\File.txt") :
+  {-# LINE 854 "src/System/Path/Internal.hs" #-}
+  ("Windows.makeRelative \"c:\\\\tmp\\\\somedir\" \"c:\\\\tmp\\\\somedir\\\\anotherdir\\\\dir\" == Windows.asRelDir \"anotherdir\\\\dir\"",
+      Windows.makeRelative "c:\\tmp\\somedir" "c:\\tmp\\somedir\\anotherdir\\dir" == Windows.asRelDir "anotherdir\\dir") :
+  {-# LINE 867 "src/System/Path/Internal.hs" #-}
+  ("Posix.makeAbsolute \"/tmp\" \"file.txt\"      == Posix.asAbsFile \"/tmp/file.txt\"",
+      Posix.makeAbsolute "/tmp" "file.txt"      == Posix.asAbsFile "/tmp/file.txt") :
+  {-# LINE 868 "src/System/Path/Internal.hs" #-}
+  ("Posix.makeAbsolute \"/tmp\" \"adir/file.txt\" == Posix.asAbsFile \"/tmp/adir/file.txt\"",
+      Posix.makeAbsolute "/tmp" "adir/file.txt" == Posix.asAbsFile "/tmp/adir/file.txt") :
+  {-# LINE 869 "src/System/Path/Internal.hs" #-}
+  ("Posix.makeAbsolute \"/tmp\" \"adir/dir\"      == Posix.asAbsDir \"/tmp/adir/dir\"",
+      Posix.makeAbsolute "/tmp" "adir/dir"      == Posix.asAbsDir "/tmp/adir/dir") :
+  {-# LINE 881 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asRelFile \"file.txt\")       == \"/tmp/file.txt\"",
+      Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "file.txt")       == "/tmp/file.txt") :
+  {-# LINE 882 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asRelFile \"adir/file.txt\")  == \"/tmp/adir/file.txt\"",
+      Posix.genericMakeAbsolute "/tmp" (Posix.asRelFile "adir/file.txt")  == "/tmp/adir/file.txt") :
+  {-# LINE 883 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asAbsFile \"adir/file.txt\")  == \"/adir/file.txt\"",
+      Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "adir/file.txt")  == "/adir/file.txt") :
+  {-# LINE 884 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericMakeAbsolute \"/tmp\" (Posix.asAbsFile \"/adir/file.txt\") == \"/adir/file.txt\"",
+      Posix.genericMakeAbsolute "/tmp" (Posix.asAbsFile "/adir/file.txt") == "/adir/file.txt") :
+  {-# LINE 929 "src/System/Path/Internal.hs" #-}
+  ("Posix.isAbsolute (Posix.asAbsFile \"fred\")",
+      Posix.isAbsolute (Posix.asAbsFile "fred")) :
+  {-# LINE 930 "src/System/Path/Internal.hs" #-}
+  ("Posix.isAbsolute (Posix.asAbsFile \"/fred\")",
+      Posix.isAbsolute (Posix.asAbsFile "/fred")) :
+  {-# LINE 931 "src/System/Path/Internal.hs" #-}
+  ("Windows.isAbsolute (Windows.asAbsFile \"\\\\fred\")",
+      Windows.isAbsolute (Windows.asAbsFile "\\fred")) :
+  {-# LINE 932 "src/System/Path/Internal.hs" #-}
+  ("Windows.isAbsolute (Windows.asAbsFile \"c:\\\\fred\")",
+      Windows.isAbsolute (Windows.asAbsFile "c:\\fred")) :
+  {-# LINE 948 "src/System/Path/Internal.hs" #-}
+  ("Posix.isRelative (Posix.asRelFile \"fred\")",
+      Posix.isRelative (Posix.asRelFile "fred")) :
+  {-# LINE 949 "src/System/Path/Internal.hs" #-}
+  ("Posix.isRelative (Posix.asRelFile \"/fred\")",
+      Posix.isRelative (Posix.asRelFile "/fred")) :
+  {-# LINE 950 "src/System/Path/Internal.hs" #-}
+  ("Windows.isRelative (Windows.asRelFile \"fred\")",
+      Windows.isRelative (Windows.asRelFile "fred")) :
+  {-# LINE 964 "src/System/Path/Internal.hs" #-}
+  ("null (Posix.takeExtension x) == not (Posix.hasAnExtension x)",
+      null (Posix.takeExtension x) == not (Posix.hasAnExtension x)) :
+  {-# LINE 970 "src/System/Path/Internal.hs" #-}
+  ("Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.hs\")",
+      Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs")) :
+  {-# LINE 971 "src/System/Path/Internal.hs" #-}
+  ("Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.bak.hs\")",
+      Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.bak.hs")) :
+  {-# LINE 972 "src/System/Path/Internal.hs" #-}
+  ("not $ Posix.hasExtension \".hs\" (Posix.asRelFile \"MyCode.hs.bak\")",
+      not $ Posix.hasExtension ".hs" (Posix.asRelFile "MyCode.hs.bak")) :
+  {-# LINE 990 "src/System/Path/Internal.hs" #-}
+  ("Posix.extSeparator == '.'",
+      Posix.extSeparator == '.') :
+  {-# LINE 1001 "src/System/Path/Internal.hs" #-}
+  ("Posix.isPathSeparator Posix.pathSeparator",
+      Posix.isPathSeparator Posix.pathSeparator) :
+  {-# LINE 1008 "src/System/Path/Internal.hs" #-}
+  ("Posix.pathSeparator `elem` Posix.pathSeparators",
+      Posix.pathSeparator `elem` Posix.pathSeparators) :
+  {-# LINE 1019 "src/System/Path/Internal.hs" #-}
+  ("Posix.isExtSeparator a == (a == Posix.extSeparator)",
+      Posix.isExtSeparator a == (a == Posix.extSeparator)) :
+  {-# LINE 1026 "src/System/Path/Internal.hs" #-}
+  ("Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)",
+      Posix.isPathSeparator a == (a `elem` Posix.pathSeparators)) :
+  {-# LINE 1032 "src/System/Path/Internal.hs" #-}
+  ("Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)",
+      Posix.isSearchPathSeparator a == (a == Posix.searchPathSeparator)) :
+  {-# LINE 1048 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericAddExtension \"/\" \"x\" == Posix.asAbsDir \"/.x\"",
+      Posix.genericAddExtension "/" "x" == Posix.asAbsDir "/.x") :
+  {-# LINE 1049 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericAddExtension \"/a\" \"x\" == Posix.asAbsDir \"/a.x\"",
+      Posix.genericAddExtension "/a" "x" == Posix.asAbsDir "/a.x") :
+  {-# LINE 1050 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericAddExtension \"\" \"x\" == Posix.asRelFile \".x\"",
+      Posix.genericAddExtension "" "x" == Posix.asRelFile ".x") :
+  {-# LINE 1051 "src/System/Path/Internal.hs" #-}
+  ("Posix.genericAddExtension \"\" \"\" == Posix.asRelFile \"\"",
+      Posix.genericAddExtension "" "" == Posix.asRelFile "") :
   []
diff --git a/test/TestTemplate.hs b/test/TestTemplate.hs
--- a/test/TestTemplate.hs
+++ b/test/TestTemplate.hs
@@ -1,11 +1,13 @@
 {-# LANGUAGE OverloadedStrings #-}
 module TestResult (results) where
 
-import System.Path.Posix as Path
+import qualified System.Path.Posix as Posix
+import qualified System.Path.Windows as Windows
+import System.Path ((</>), (<.>))
 import Data.Char (toLower)
 
 
-results :: Char -> Path.FilePath ar -> [(String, Bool)]
+results :: (Posix.AbsRelClass ar) => Char -> Posix.FilePath ar -> [(String, Bool)]
 results a x =
   <TESTS_GO_HERE>
   []
diff --git a/tool/CreateTest.hs b/tool/CreateTest.hs
--- a/tool/CreateTest.hs
+++ b/tool/CreateTest.hs
@@ -20,11 +20,23 @@
 
 main :: IO ()
 main = do
+  let mapSndF f (a,b) = (,) a <$> f b
+  let readFileNumbered path =
+        zipWith (\n row -> ((path,n), row)) [(0::Int)..] . lines <$>
+        readFile path
   testLines <-
-     mapMaybe (stripPrefix testPrefix) . concatMap lines <$> mapM readFile srcfiles
+     mapMaybe (mapSndF $ stripPrefix testPrefix) . concat <$>
+        mapM readFileNumbered srcfiles
   (templateHead,_:templateTail) <-
      break (tok `isInfixOf`) . lines <$> readFile template
-  let outLines = (\t -> printf "  (%s,\n    %s) :" (show t) t) <$> testLines
+  {-
+  Choose the same indentation depth as in the source file,
+  such that GHC reports precise source file locations.
+  -}
+  let outLines =
+        (\((src,n),t) ->
+           printf "  {-# LINE %d \"%s\" #-}\n  (%s,\n      %s) :"
+              n src (show t) t) <$> testLines
 
   writeFile testModule $ unlines $
      ("{- Do not edit! Created from " ++ template ++ " -}") :
