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

Andrew Pimlott andrew at pimlott.net
Tue Jul 25 21:37:23 EDT 2006

[Sorry for the late reply.]

On Wed, Jul 19, 2006 at 03:16:48AM +0100, Neil Mitchell wrote:
> >> I want to make sure a filename is valid. For example, "prn" and "con"
> >This is another rat's nest, so I suggest that it be dealt with
> >separately from the basic filepath module.  The notion of "valid" is
> >squishy:  It depends entirely on what you intend to do with the path.
> Its a rats nest to do it properly, but some very basic idea of "does
> this path have things which there is no way could possibly be in a
> file" - for example c:\|file is a useful thing to have.

This seems to encourage the classic mistake of checking "not known bad"
rather than "known good".  "known bad" is rarely useful in my
experience.  What use case do you have in mind?

> >> In this library proposal, there are a bunch of "xxxDrive" functions
> >> that many Unix-oriented programmers are sure to ignore because they are
> >> no-ops on Unixy systems. Even on Windows, they are not very useful:
> >
> >I strongly agree about this.  The temptation in path modules seems to be
> >to throw in everything you can think of (without specifying any of it
> >precisely), just in case someone finds it useful.
> 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
portable functions.  (In my design, I have separate types for Windows
and Unix paths, and imagine full support for Windows-specific
operations, but only on the Windows type.)

> I have tried to specify the functions precisely, and I use this
> specification as a test suite. Currently there are 114 properties in
> this test suite, all can be seen on the haddock documentation. If you
> consider any function to be ambiguously specified, please say which
> one and I'll add extra tests until it gives you no suprises at all.

My criticism is that your properties are all specified in terms of
string manipulation.  The whole point of paths is that they are
interpreted by the system, so if you neglect to say what your operations
mean to the system, what have you specified?

Here are some specific cases I take issue with.  (Quotes are from your
generated docs.)  Sorry if I seem to be piling it on, but I think these
matters are important for a good path library.

> pathSeparator :: Char
> The character that seperates directories.

So what do I do with this?  If I need it, it seems like the module has

> splitFileName :: FilePath -> (String, String)
> Split a filename into directory and file. 

Which directory and which file?

> splitFileName "bob" == ("", "bob")

"" is not a directory.

> Windows: splitFileName "c:" == ("c:","")

"c:" is arguably not a directory.  (Consider that "dir c:" lists the
current directory on c:, not c:\)

> getFileName "test/" == ""

"" is not a filename.

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.

> setFileName :: FilePath -> String -> FilePath
> Set the filename. 

This is vague to me.  Eg, what does it do with "/", which has no

> getDirectory :: FilePath -> FilePath
> Get the directory name, move up one level. 

What does this mean, in the presence of dots and symlinks?

> normalise :: FilePath -> FilePath
> Normalise a file

As Simon asked, when is this safe to use?

> equalFilePath :: FilePath -> FilePath -> Bool
> Equality of two FilePaths. If you call fullPath first this has a much
> better chance of working. Note that this doesn't follow symlinks or
> DOSNAM~1s.

As you acknowledge, it's a crap-shoot.  So what's the point?

> isValid :: FilePath -> Bool
> Is a FilePath valid, i.e. could you create a file like it? 

There are a whole host of reasons you might not be able to create a
file.  Which ones does this address?

> >I tried to export a minimal set of operations that seem to me sufficient
> >for everything not very platform-specific (though I am interested in
> >counterexamples):
> Anything to do with file extensions? Its also important (I feel) for
> people to have easy access to common operations, but I guess that is a
> design decision.

I think of that as a separate module, because extensions have no meaning
to the system and can be done with portable, functional code, as far as
I understand.


More information about the Haskell-Cafe mailing list