Skip to content

Commit

Permalink
Add user documentation in the exposed Path module
Browse files Browse the repository at this point in the history
  • Loading branch information
harendra-kumar committed Dec 30, 2024
1 parent 7a33ce2 commit 6479343
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 85 deletions.
92 changes: 92 additions & 0 deletions core/src/Streamly/FileSystem/Path.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,98 @@
-- Maintainer : [email protected]
-- Portability : GHC
--
-- Well typed, flexible, extensible and efficient file systems paths,
-- preserving the OS and filesystem encoding.
--
-- /Flexible/: you can choose the level of type safety you want. 'Path' is the
-- basic path type which can represent a file, directory, absolute or relative
-- path with no restrictions. Depending on how much type safety you want, you
-- can choose appropriate type wrappers or a combination of those to wrap the
-- 'Path' type.
--
-- = Rooted Paths vs Path Segments
--
-- For the safety of the path append operation we make the distinction of
-- rooted paths vs path segments. A path that starts from some implicit or
-- explicit root in the file system is a rooted path, for example, @\/usr\/bin@
-- is a rooted path starting from an explicit file system root directory @/@.
-- Similarly, @.\/bin@ is a path with an implicit root, this path is hanging
-- from the current directory. A path that is not rooted is called a path
-- segment e.g. @local\/bin@ is a segment.
--
-- This distinction affords safety to the path append operation. We can always
-- append a segment to a rooted path or to another segment. However, it does
-- not make sense to append a rooted path to another rooted path. The default
-- append operation in the Path module checks for this and fails if the
-- operation is incorrect. However, the programmer can force it by using the
-- unsafe version of append operation. You can also drop the root explicitly
-- and use the safe append operation.
--
-- The "Streamly.FileSystem.Path.LocSeg" module provides explicit typing of
-- rooted paths vs path segments. Rooted paths are represented by the @Loc
-- Path@ type and path segments are represented by the @Seg Path@ type. If you
-- use the 'Path' type then append can fail if you try to append a rooted
-- location to another path, but if you use @Loc Path@ or @Seg Path@ types then
-- append can never fail at run time as the types would not allow it at compile
-- time.
--
-- = Absolute vs Relative Rooted Paths
--
-- Rooted paths can be absolute or relative. Absolute paths have an absolute
-- root e.g. @\/usr\/bin@. Relative paths have a dynamic or relative root e.g.
-- @.\/local\/bin@, or @.@, in these cases the root is current directory which
-- is not absolute but can change dynamically. Note that there is no type level
-- distinction for absolute and relative paths.
--
-- = File vs Directory Paths
--
-- Independently of the rooted or segment distinction you can also make the
-- distinction between files and directories using the
-- "Streamly.FileSystem.Path.FileDir" module. @File Path@ type represents a
-- file whereas @Dir Path@ represents a directory. It provides safety against
-- appending a path to a file. Append operation does not allow appending to
-- 'File' types.
--
-- By default a path with a trailing separator is implicitly considered a
-- directory path. However, the absence of a trailing separator does not convey
-- any information, it could either be a directory or a file. Thus the append
-- operation allows appending to even the paths that do not have a trailing
-- separator. However, when creating a typed path of 'File' type the conversion
-- fails unless we explicitly drop the trailing separator.
--
-- = Flexible Typing
--
-- You can use the 'Loc', 'Seg' or 'Dir', 'File' types independent of each
-- other by using only the required module. If you want both types of
-- distinctions then you can use them together as well using the
-- "Streamly.FileSystem.Path.Typed" module. For example, the @Loc (Dir Path)@
-- represents a rooted path which is a directory. You can only append to a path
-- that has 'Dir' in it and you can only append a 'Seg' type.
--
-- You can choose to use just the basic 'Path' type or any combination of safer
-- types. You can upgrade or downgrade the safety using the @adapt@ operation.
-- Whenever a less restrictive path type is converted to a more restrictive
-- path type, the conversion involves run-time checks and it may fail. However,
-- a more restrictive path type can be freely converted to a less restrictive
-- one.
--
-- = Extensibility
--
-- Extensible, you can define your own newtype wrappers similar to 'File' or
-- 'Dir' to provide custom restrictions if you want.
--
-- = Compatibility
--
-- Any path type can be converted to the 'FilePath' type using the 'toString'
-- operation. Operations to convert to and from 'OsPath' type at zero cost are
-- provided in the @streamly-filepath@ package. This is possible because the
-- types use the same underlying representation as the 'OsPath' type.
--
-- = String Creation Quasiquoter
--
-- You may find the 'str' quasiquoter from "Streamly.Unicode.String" to be
-- useful in creating paths.
--

module Streamly.FileSystem.Path
(
Expand Down
93 changes: 8 additions & 85 deletions core/src/Streamly/Internal/FileSystem/Path.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,20 @@
-- Maintainer : [email protected]
-- Portability : GHC
--
-- = User Notes
--
-- Well typed, flexible, extensible and efficient file systems paths,
-- preserving the OS and filesystem encoding.
--
-- /Flexible/: you can choose the level of type safety you want. 'Path' is the
-- basic path type which can represent a file, directory, absolute or relative
-- path with no restrictions. Depending on how much type safety you want, you
-- can choose appropriate type wrappers or a combination of those to wrap the
-- 'Path' type.
--
-- The basic type-safety is provided by the
-- "Streamly.Internal.FileSystem.PosixPath.LocSeg" module. We make a
-- distinction between two types of paths viz. locations and segments.
-- Locations are represented by the @Loc Path@ type and path segments are
-- represented by the @Seg Path@ type.
--
-- Locations are rooted paths, they have a "root" attached to them. Rooted
-- paths can be absolute or relative. Absolute paths have an absolute root e.g.
-- @\/usr\/bin@. Relative paths have a dynamic or relative root e.g.
-- @.\/local\/bin@, or @.@, in these cases the root is current directory which
-- is not absolute but can change dynamically, nevertheless these are rooted
-- paths as they still refer to a specific location starting from some root in
-- the file system even though the root is decided dynamically.
--
-- In contrast to rooted paths, path segments are simply a sequence of path
-- components without any reference to a root or specific starting location
-- e.g. @usr\/bin@, @local\/bin@, or @../bin@ are simply path segments which
-- can be attached to any other path or segment to augment it. This distinction
-- is made to allow for safe append operation on paths, you can only append
-- path segments to any path, a rooted path cannot be appended to another path.
-- If you use the 'Path' type then append can fail if you try to append a
-- rooted location to another path, but if you use @Loc Path@ or @Seg Path@
-- types then append can never fail at run time as the types would not allow
-- it.
--
-- To summarize the conceptual distinctions:
-- * Path
-- * Rooted location
-- * Absolute
-- * Relative
-- * Unrooted segment
--
-- Independently of the location or segment distinction you can also make the
-- distinction between files and directories using the
-- "Streamly.Internal.FileSystem.PosixPath.FileDir" module. @File Path@ type
-- represents a file whereas @Dir Path@ represents a directory. It provides
-- safety against appending a path to a file. Append operation allows appending
-- to only 'Dir' types.
--
-- You can use the 'Loc', 'Seg' or 'Dir', 'File' types independent of each
-- other by using only the required module. If you want both types of
-- distinctions then you can use them together as well using the
-- "Streamly.Internal.FileSystem.PosixPath.Typed" module. For example, the
-- @Loc (Dir Path)@ represents a location which is a directory. You can only
-- append to a path that has 'Dir' in it and you can only append a 'Seg' type.
--
-- You can choose to use just the basic 'Path' type or any combination of safer
-- types. You can upgrade or downgrade the safety using the @adapt@ operation.
-- Whenever a less restrictive path type is converted to a more restrictive
-- path type, the conversion involves run-time checks and it may fail. However,
-- a more restrictive path type can be freely converted to a less restrictive
-- one.
--
-- Extensible, you can define your own newtype wrappers similar to 'File' or
-- 'Dir' to provide custom restrictions if you want.
--
-- Any path type can be converted to the 'FilePath' type using the 'toString'
-- operation. Operations to convert to and from 'OsPath' type at zero cost are
-- provided in the @streamly-filepath@ package. The types use the same
-- underlying representation as the 'OsPath' type.
--
-- = Developer Notes:
-- == References
--
-- * https://en.wikipedia.org/wiki/Path_(computing)
-- * https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
-- * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc
--
-- == Windows and Posix Paths
--
-- We should be able to manipulate windows paths on posix and posix paths on
-- windows as well. Therefore, we have WindowsPath and PosixPath types which
-- are supported on both platforms. However, the Path module aliases Path to
-- WindowsPath on Windows and PosixPath on Posix.
--
-- Conventions: A trailing separator on a path indicates that it is a
-- directory. However, the absence of a trailing separator does not convey any
-- information, it could either be a directory or a file.
--
-- You may also find the 'str' quasiquoter from "Streamly.Unicode.String" to be
-- useful in creating paths.
--
-- * https://en.wikipedia.org/wiki/Path_(computing)
-- * https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
-- * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc
--
-- == File System Tree
-- == File System as Tree vs Graph
--
-- A file system is a tree when there are no hard links or symbolic links. But
-- in the presence of symlinks it could be a DAG or a graph, because directory
Expand Down

0 comments on commit 6479343

Please sign in to comment.