
Hi
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?
wget on windows saves web pages such as "http://www.google.com/index.html?q=haskell" to the file "index.html?q=haskell". This just doesn't work, and is the main reason I added this in. I don't think it will be a commonly used operation.
The drive functions stand on their own as a chunk, and are possibly 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. I agree, and have now removed them.
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? True, but at the same time specifying what something means with respect to a filesystem is very hard :) If you had any insight how this could be done I'd be interested.
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. Hopefully no one will ever use it. Its part of the low level functions that the FilePath module builds on. However, pragmatically, someone somewhere will have a use for it, and the second they do they'll just write '/', and at that point we've lost.
splitFileName :: FilePath -> (String, String) Split a filename into directory and file. Which directory and which file? Ok, thats probably the wrong description. Splits off the last filename would be a better description, leaving the rest.
splitFileName "bob" == ("", "bob") "" is not a directory No, its "the rest" in this context.
Windows: splitFileName "c:" == ("c:","") "c:" is arguably not a directory. (Consider that "dir c:" lists the current directory on c:, not c:\) Its a bit weird on Windows, but certainly "c:" isn't a FileName, so thats the reason for this decision.
getFileName "test/" == "" "" is not a filename. But test/ is certainly not a file.
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. That was something I thought over quite a while. If the user enters "directory/" then they do not mean the file called directory, they mean the directory called directory. And in Windows certainly you can't open a file called "file/"
setFileName :: FilePath -> String -> FilePath Set the filename. This is vague to me. Eg, what does it do with "/", which has no filename? "/" as the second element? I guess its calling it out of spec if you use anything but a valid filename as the second argument, and the behaviour is undefined. If you do need to do something like that, then combine is the function.
getDirectory :: FilePath -> FilePath Get the directory name, move up one level. What does this mean, in the presence of dots and symlinks? It gets a parent directory, there may be one, but the one returned will be a parent.
normalise :: FilePath -> FilePath Normalise a file As Simon asked, when is this safe to use? Let me think, and then work on it so the answer is always.
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? Its a case of reality, at the moment people use == to test if two file paths are equal, at least this is a better test.
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 have added documentation which hopefully shows exactly what it tries to address.
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. Not really, what about getExtension "file.ext\lump" - the answer is "" on windows and ".ext\lump" on Posix. This library isn't just a portability layer (although it does encompass that), its mainly meant to make the things people do with filepaths easier, and by seducing them with ease of use, subtly tack in cross platform portability.
Thanks Neil