[Haskell-cafe] RE: ANN: System.FilePath 0.9

Udo Stenzel u.stenzel at web.de
Wed Jul 26 09:29:01 EDT 2006


Andrew Pimlott wrote:
> > The drive functions stand on their own as a chunk, and are possibly
> > not well suited to a Posix system, but are critical for a Windows
> > system.
> 
> Why are they critical for portable code?  I am fine with
> Windows-specific functions, but I think it's a mistake to bundle them
> [with] portable functions.

I couldn't agree more.  In fact, why can't we pretend the world is sane
at least within Haskell and just put away those drive letters?


> My criticism is that your properties are all specified in terms of
> string manipulation.

Exactly.  I believe, a FilePath should be an algebraic datatype.
Most operations on that don't have to be specified, because they are
simple and have an obvious effect.  Add a system specific parser and a
system specific renderer, maybe also define a canonical format, and the
headaches stop.  What's wrong with this?

data FilePath = Absolute RelFilePath | Relative RelFilePath
data RelFilePath = ThisDirectory 
                 | File String
                 | ParentOf RelFilePath 
                 | String :|: RelFilePath

parseSystemPath :: String -> Maybe FilePath
renderSystemPath :: FilePath -> String

We can even clearly distiguish between the name of a directory in its
parent and the directory itself.  On Windows, the root directory just
contains the drive letters and is read-only,
drive-absolute-but-directory-relative paths are simply ignored (they are
a dumb idea anyway).  Seperator characters are never exposed, all we
need now is a mapping from Unicode to whatever the system wants.  



> > pathSeparator :: Char
> > The character that seperates directories.
> 
> So what do I do with this?  If I need it, it seems like the module has
> failed.

Indeed.

 
> > splitFileName "bob" == ("", "bob")
> 
> "" is not a directory.

Some problems just vanish:

parseSystemPath "bob" == Just (Relative (File "bob"))
splitFileName (Relative (File "bob")) = (Relative ThisDirectory, File "bob")

 
> > Windows: splitFileName "c:" == ("c:","")
> 
> "c:" is arguably not a directory.

parseSystemPath "c:" == Nothing
parseSystemPath "c:\" == Absolute ("C:" :|: ThisDirectory)


> (Consider that "dir c:" lists the current directory on c:, not c:\)

I'd rather ignore that altogether.  Multiple roots with associated
"current directories" are just a needless headache.  Even a "current
directory" is somewhat ill-fitted for a functional language like
Haskell.


> > getFileName "test/" == ""
> 
> "" is not a filename.

getFileName (Relative ("test" :|: ThisDirectory))
	== error "pattern match failure"

 
> Also, it looks from this that you treat paths differently depending on
> whether they end in a separator.  Yet this makes no difference to the
> system.  That seems wrong to me.

Not to the system, but some programs like to make a difference.  If you
give rsync a path that doesn't end in a slash, it will take that to mean
the directory.  With a slash, it means the contents of the directory.
The difference is an additional path component that ends up on the
target file system or doesn't.

 
> > getDirectory :: FilePath -> FilePath
> > Get the directory name, move up one level. 
> 
> What does this mean, in the presence of dots and symlinks?

You're right, this has to be ill-defined.  Instead it should be

moveUp :: FilePath -> IO FilePath

which would end up in the parent of the linked-to directory after
following a symlink.  Cutting of a component is done by simple pattern
matching, no special functions needed.


Sorry for the rant, but this is Haskell, not Perl.  We have true data
types, not just strings...


Udo.
-- 
A politician is someone who calls a spade a portable, hand-operated
digging implement.
	-- author unknown
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org//pipermail/haskell-cafe/attachments/20060726/ca06146e/attachment.bin


More information about the Haskell-Cafe mailing list