Skip to content

Commit 82d6fcd

Browse files
committed
Improve README
1 parent 1d984dd commit 82d6fcd

File tree

3 files changed

+47
-20
lines changed

3 files changed

+47
-20
lines changed

HACKING.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Hacking
2+
3+
Most of the code is in `System/FilePath/Internal.hs` which is `cpphs`'d into both `System/FilePath/Posix.hs`
4+
and `System/FilePath/Windows.hs` via `make cpp` and commited to the repo. This Internal module is a bit weird
5+
in that it isn't really a Haskell module, but is more an include file.
6+
7+
The library has extensive doc tests. Anything starting with `-- >` is transformed into a doc test as a predicate
8+
that must evaluate to `True`. These tests follow a few rules:
9+
10+
* Tests prefixed with `Windows:` or `Posix:` are only tested against that specific
11+
implementation - otherwise tests are run against both implementations.
12+
* Any single letter variable, e.g. `x`, is considered universal quantification, and is checked with `QuickCheck`.
13+
* If `Valid x =>` appears at the start of a doc test, that means the property
14+
will only be tested with `x` passing the `isValid` predicate.
15+
16+
The tests can be generated by `make gen` in the root of the repo, and will be placed in `tests/TestGen.hs`.
17+
The `TestGen.hs` file is checked into the repo, and the CI scripts check that `TestGen.hs` is in sync with
18+
what would be generated a fresh - if you don't regenerate `TestGen.hs` the CI will fail.
19+
20+
The `.ghci` file is set up to allow you to type `ghci` to open the library, then `:go` will regenerate the
21+
tests and run them.

README.md

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,38 @@
11
# FilePath [![Hackage version](https://img.shields.io/hackage/v/filepath.svg?label=Hackage)](https://hackage.haskell.org/package/filepath)
22

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:
45

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.
812

913
All three modules provide the same API, and the same documentation (calling out differences in the different variants).
1014

11-
### Should `FilePath` be an abstract data type?
15+
### What is a `FilePath`?
1216

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.
1418

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.
2022

21-
### Developer notes
23+
On windows (at least the API used by `Win32`) filepaths are UTF-16 strings.
2224

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.
2428

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).
2632

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:
3034

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)

filepath.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extra-source-files:
2828
System/FilePath/Internal.hs
2929
extra-doc-files:
3030
README.md
31+
HACKING.md
3132
changelog.md
3233

3334
source-repository head

0 commit comments

Comments
 (0)