System.FilePath.Posixmanipulates POSIX/Linux style
/as the path separator).
System.FilePath.Windowsmanipulates Windows style
FilePathvalues (with either
/as the path separator, and deals with drives).
System.FilePathis an alias for the module appropriate to your platform.
All three modules provide the same API, and the same documentation (calling out differences in the different variants).
FilePath be an abstract data type?
The answer for this library is "no". While an abstract
FilePath has some advantages (mostly type safety), it also has some disadvantages:
- In Haskell the definition is
type FilePath = String, and all file-oriented functions operate on this type alias, e.g.
writeFile. Any abstract type would require wrappers for these functions or lots of casts between
Stringand the abstraction.
- It is not immediately obvious what a
FilePathis, and what is just a pure
String. For example,
- Often it is useful to represent invalid files, e.g.
/foo/*.txtprobably isn't an actual file, but a glob pattern. Other programs use
foo//barfor globs, which is definitely not a file, but might want to be stored as a
- Some programs use syntactic non-semantic details of the
FilePathto change their behaviour. For example,
foo/.are all similar, and refer to the same location on disk, but may behave differently when passed to command-line tools.
- A useful step to introducing an abstract
FilePathis to reduce the amount of manipulating
FilePathvalues like lists. This library hopes to help in that effort.
Most of the code is in
System/FilePath/Internal.hs which is
#include'd into both
System/FilePath/Windows.hs with the
IS_WINDOWS CPP define set to either
False. This Internal module is a bit weird in that it isn't really a Haskell module, but is more an include file.
The library has extensive doc tests. Anything starting with
-- > is transformed into a doc test as a predicate that must evaluate to
True. These tests follow a few rules:
- Tests prefixed with
Posix:are only tested against that specific implementation - otherwise tests are run against both implementations.
- Any single letter variable, e.g.
x, is considered universal quantification, and is checked with
Valid x =>appears at the start of a doc test, that means the property will only be tested with
The tests can be generated by
Generate.hs in the root of the repo, and will be placed in
TestGen.hs file is checked into the repo, and the CI scripts check that
TestGen.hs is in sync with what would be generated a fresh - if you don't regenerate
TestGen.hs the CI will fail.
.ghci file is set up to allow you to type
ghci to open the library, then
:go will regenerate the tests and run them.