Path

path-0.5.7: Support for well-typed paths

Copyright | © 2015–2016 FP Complete
License | BSD 3 clause
Maintainer | Chris Done <chrisdone@fpcomplete.com>
Stability | experimental
Portability | portable
Safe Haskell | None
Language | Haskell98

Path

Contents

- Types
- Parsing
- Constructors
- Operations
- Conversion

Description

Support for well-typed paths.

Synopsis

- data Path b t
- data Abs
- data Rel
- data File
- data Dir
- parseAbsDir :: MonadThrow m => FilePath -> m (Path Abs Dir)
- parseRelDir :: MonadThrow m => FilePath -> m (Path Rel Dir)
- parseAbsFile :: MonadThrow m => FilePath -> m (Path Abs File)
- parseRelFile :: MonadThrow m => FilePath -> m (Path Rel File)
- data PathParseException
- mkAbsDir :: FilePath -> Q Exp
- mkRelDir :: FilePath -> Q Exp
- mkAbsFile :: FilePath -> Q Exp
- mkRelFile :: FilePath -> Q Exp
- (</>) :: Path b Dir -> Path Rel t -> Path b t
- stripDir :: MonadThrow m => Path b Dir -> Path b t -> m (Path Rel t)
- isParentOf :: Path b Dir -> Path b t -> Bool
- parent :: Path Abs t -> Path Abs Dir
- filename :: Path b File -> Path Rel File
- dirname :: Path b Dir -> Path Rel Dir
- toFilePath :: Path b t -> FilePath
- fromAbsDir :: Path Abs Dir -> FilePath
- fromRelDir :: Path Rel Dir -> FilePath
- fromAbsFile :: Path Abs File -> FilePath
- fromRelFile :: Path Rel File -> FilePath

# Types

data Path b t

Path of some base and type.

Internally is a string. The string can be of two formats only:

1. File format: `file.txt`, `foo/bar.txt`, `/foo/bar.txt`
2. Directory format: `foo/`, `/foo/bar/`

All directories end in a trailing separator. There are no duplicate path separators `//`, no `..`, no `./`, no `~/`, etc.

Instances

Eq (Path b t) | String equality. The following property holds:
    show x == show y ≡ x == y
Ord (Path b t) | String ordering. The following property holds:
    show x `compare` show y ≡ x `compare` y
Show (Path b t) | Same as `toFilePath`. The following property holds:
    x == y ≡ show x == show y
NFData (Path b t) |

data Abs

An absolute path.

data Rel

A relative path; one without a root.

data File

A file path.

data Dir

A directory path.

# Parsing

parseAbsDir :: MonadThrow m => FilePath -> m (Path Abs Dir)

Get a location for an absolute directory. Produces a normalized path which always ends in a path separator.

Throws: `PathParseException`

parseRelDir :: MonadThrow m => FilePath -> m (Path Rel Dir)

Get a location for a relative directory. Produces a normalized path which always ends in a path separator.

Note that `filepath` may contain any number of `./` but may not consist solely of `./`. It also may not contain a single `..` anywhere.

Throws: `PathParseException`

parseAbsFile :: MonadThrow m => FilePath -> m (Path Abs File)

Get a location for an absolute file.

Throws: `PathParseException`

parseRelFile :: MonadThrow m => FilePath -> m (Path Rel File)

Get a location for a relative file.

Note that `filepath` may contain any number of `./` but may not contain a single `..` anywhere.

Throws: `PathParseException`

data PathParseException

Exception when parsing a location.

Instances

Show PathParseException |
Exception PathParseException |

# Constructors

mkAbsDir :: FilePath -> Q Exp

Make a 'Path Abs Dir'.

Remember: due to the nature of absolute paths this (e.g. `/home/foo`) may compile on your platform, but it may not compile on another platform (Windows).

mkRelDir :: FilePath -> Q Exp

Make a 'Path Rel Dir'.

mkAbsFile :: FilePath -> Q Exp

Make a 'Path Abs File'.

Remember: due to the nature of absolute paths this (e.g. `/home/foo`) may compile on your platform, but it may not compile on another platform (Windows).

mkRelFile :: FilePath -> Q Exp

Make a 'Path Rel File'.

# Operations

(</>) :: Path b Dir -> Path Rel t -> Path b t

Append two paths.

The following cases are valid and the equalities hold:

    $(mkAbsDir x) </> $(mkRelDir y) = $(mkAbsDir (x ++ "/" ++ y))

    $(mkAbsDir x) </> $(mkRelFile y) = $(mkAbsFile (x ++ "/" ++ y))

    $(mkRelDir x) </> $(mkRelDir y) = $(mkRelDir (x ++ "/" ++ y))

    $(mkRelDir x) </> $(mkRelFile y) = $(mkRelFile (x ++ "/" ++ y))

The following are proven not possible to express:

    $(mkAbsFile …) </> x

    $(mkRelFile …) </> x

    x </> $(mkAbsFile …)

    x </> $(mkAbsDir …)

stripDir :: MonadThrow m => Path b Dir -> Path b t -> m (Path Rel t)

Strip directory from path, making it relative to that directory. Throws `Couldn'tStripPrefixDir` if directory is not a parent of the path.

The following properties hold:

    stripDir x (x </> y) = y

Cases which are proven not possible:

    stripDir (a :: Path Abs …) (b :: Path Rel …)

    stripDir (a :: Path Rel …) (b :: Path Abs …)

In other words the bases must match.

isParentOf :: Path b Dir -> Path b t -> Bool

Is p a parent of the given location? Implemented in terms of `stripDir`. The bases must match.

parent :: Path Abs t -> Path Abs Dir

Take the absolute parent directory from the absolute path.

The following properties hold:

    parent (x </> y) == x

On the root, getting the parent is idempotent:

    parent (parent "/") = "/"

filename :: Path b File -> Path Rel File

Extract the file part of a path.

The following properties hold:

    filename (p </> a) == filename a

dirname :: Path b Dir -> Path Rel Dir

Extract the last directory name of a path.

The following properties hold:

    dirname (p </> a) == dirname a

# Conversion

toFilePath :: Path b t -> FilePath

Convert to a `FilePath` type.

All directories have a trailing slash, so if you want no trailing slash, you can use `dropTrailingPathSeparator` from the filepath package.

fromAbsDir :: Path Abs Dir -> FilePath

Convert absolute path to directory to `FilePath` type.

fromRelDir :: Path Rel Dir -> FilePath

Convert relative path to directory to `FilePath` type.

fromAbsFile :: Path Abs File -> FilePath

Convert absolute path to file to `FilePath` type.

fromRelFile :: Path Rel File -> FilePath

Convert relative path to file to `FilePath` type.