|
1 | 1 | # FilePath [](https://hackage.haskell.org/package/filepath)
|
2 | 2 |
|
3 |
| -The `filepath` package provides functionality for manipulating `FilePath` values, and is shipped with both [GHC](https://www.haskell.org/ghc/) and the [Haskell Platform](https://www.haskell.org/platform/). It provides three modules: |
| 3 | +The `filepath` package provides functionality for manipulating `FilePath` values, and is shipped with [GHC](https://www.haskell.org/ghc/). |
| 4 | +It provides three modules: |
4 | 5 |
|
5 |
| -* [`System.FilePath.Posix`](http://hackage.haskell.org/package/filepath/docs/System-FilePath-Posix.html) manipulates POSIX/Linux style `FilePath` values (with `/` as the path separator). |
6 |
| -* [`System.FilePath.Windows`](http://hackage.haskell.org/package/filepath/docs/System-FilePath-Windows.html) manipulates Windows style `FilePath` values (with either `\` or `/` as the path separator, and deals with drives). |
7 |
| -* [`System.FilePath`](http://hackage.haskell.org/package/filepath/docs/System-FilePath.html) is an alias for the module appropriate to your platform. |
| 6 | +* [`System.FilePath.Posix`](http://hackage.haskell.org/package/filepath/docs/System-FilePath-Posix.html) |
| 7 | + manipulates POSIX/Linux style `FilePath` values (with `/` as the path separator). |
| 8 | +* [`System.FilePath.Windows`](http://hackage.haskell.org/package/filepath/docs/System-FilePath-Windows.html) |
| 9 | + manipulates Windows style `FilePath` values (with either `\` or `/` as the path separator, and deals with drives). |
| 10 | +* [`System.FilePath`](http://hackage.haskell.org/package/filepath/docs/System-FilePath.html) |
| 11 | + is an alias for the module appropriate to your platform. |
8 | 12 |
|
9 | 13 | All three modules provide the same API, and the same documentation (calling out differences in the different variants).
|
10 | 14 |
|
11 |
| -### Should `FilePath` be an abstract data type? |
| 15 | +### What is a `FilePath`? |
12 | 16 |
|
13 |
| -The answer for this library is "no". While an abstract `FilePath` has some advantages (mostly type safety), it also has some disadvantages: |
| 17 | +In Haskell, the definition is `type FilePath = String` as of now. A Haskell `String` is a list of Unicode code points. |
14 | 18 |
|
15 |
| -* In Haskell the definition is `type FilePath = String`, and all file-oriented functions operate on this type alias, e.g. `readFile`/`writeFile`. Any abstract type would require wrappers for these functions or lots of casts between `String` and the abstraction. |
16 |
| -* It is not immediately obvious what a `FilePath` is, and what is just a pure `String`. For example, `/path/file.ext` is a `FilePath`. Is `/`? `/path`? `path`? `file.ext`? `.ext`? `file`? |
17 |
| -* Often it is useful to represent invalid files, e.g. `/foo/*.txt` probably isn't an actual file, but a glob pattern. Other programs use `foo//bar` for globs, which is definitely not a file, but might want to be stored as a `FilePath`. |
18 |
| -* Some programs use syntactic non-semantic details of the `FilePath` to change their behaviour. For example, `foo`, `foo/` and `foo/.` are all similar, and refer to the same location on disk, but may behave differently when passed to command-line tools. |
19 |
| -* A useful step to introducing an abstract `FilePath` is to reduce the amount of manipulating `FilePath` values like lists. This library hopes to help in that effort. |
| 19 | +On unix, filenames don't have a predefined encoding as per the |
| 20 | +<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_170 POSIX specification> |
| 21 | +and are passed as @char[]@ to syscalls. |
20 | 22 |
|
21 |
| -### Developer notes |
| 23 | +On windows (at least the API used by `Win32`) filepaths are UTF-16 strings. |
22 | 24 |
|
23 |
| -Most of the code is in `System/FilePath/Internal.hs` which is `cpphs`'d into both `System/FilePath/Posix.hs` and `System/FilePath/Windows.hs` via `make cpp` and commited to the repo. This Internal module is a bit weird in that it isn't really a Haskell module, but is more an include file. |
| 25 | +This means that Haskell filepaths have to be converted to C-strings on unix |
| 26 | +(utilizing the current filesystem encoding) and to UTF-16 strings |
| 27 | +on windows. |
24 | 28 |
|
25 |
| -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: |
| 29 | +Further, this is a low-level library and it makes no attempt at providing a more |
| 30 | +type safe variant for filepaths (e.g. by distinguishing between absolute and relative |
| 31 | +paths) and ensures no invariants (such as filepath validity). |
26 | 32 |
|
27 |
| -* Tests prefixed with `Windows:` or `Posix:` are only tested against that specific implementation - otherwise tests are run against both implementations. |
28 |
| -* Any single letter variable, e.g. `x`, is considered universal quantification, and is checked with `QuickCheck`. |
29 |
| -* If `Valid x =>` appears at the start of a doc test, that means the property will only be tested with `x` passing the `isValid` predicate. |
| 33 | +For such libraries, check out the following: |
30 | 34 |
|
31 |
| -The tests can be generated by `make gen` in the root of the repo, and will be placed in `tests/TestGen.hs`. The `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. |
32 |
| - |
33 |
| -The `.ghci` file is set up to allow you to type `ghci` to open the library, then `:go` will regenerate the tests and run them. |
| 35 | +* [hpath](https://hackage.haskell.org/package/hpath) |
| 36 | +* [path](https://hackage.haskell.org/package/path) |
| 37 | +* [paths](https://hackage.haskell.org/package/paths) |
| 38 | +* [strong-path](https://hackage.haskell.org/package/strong-path) |
0 commit comments