Proposal: System.FilePath: current directory should be ".", not ""

Simon Marlow marlowsd at
Wed Sep 23 09:17:58 EDT 2009

On 22/09/2009 16:43, Duncan Coutts wrote:
> On Mon, 2009-09-21 at 12:00 +0100, Simon Marlow wrote:
>> The main change is that
>>      splitFileName "foo" = (".", "foo")
>> and
>>     takeDirectory "foo" = "."
>> and
>>     "."</>  x  =  x
> So to re-iterate the point made in the ticket, the principle here is
> that the representation of the current directory is "." and not "". This
> lets us safely use results of System.FilePath functions as arguments to
> system and directory functions without having to check for "".
> However the principle is not without exception, we also want to elide
> the explicit representation of the current directory when it is not
> needed.
> If these are the principles then can we look at whether we apply them
> elsewhere in System.FilePath consistently?
> What about:
> joinPath [".", "foo"]
> should it be "./foo" or "foo" ?
> If "./foo" then it's not the same as</>, if the latter then we loose
> the property
> Valid x =>  joinPath (splitPath x) == x
> it would be some kind of limited normalisation.
> So I'm happy with the first two changes, I'm less convinced about
> changing</>  to elide "." on the left. Perhaps people who worry about
> leading "./" when the FilePath is displayed to the user should just use
> normalise. That's what they do now and we seem to get along ok.

So this subject was discussed between Ian and myself in the original 
thread, see e.g.

The conclusion was that in the filesystem semantics "./foo" is equal to 
"foo", but the string passed to rawSystem (and execp()) is not a 
FilePath, it is something like Either FilePath String.

However, there are some oddities with the current proposal.  e.g.

   splitFileName "./foo" == ("./", "foo")
   "./" </> "foo" == "./foo"

The current proposal just about hangs together because the tiny bit of 
normalisation that </> does exactly undoes the creation of "." in 
splitFileName, and there's no other way that splitFileName can generate 
".".  That's a terribly fragile property.

If we "fixed" </> to do more normalisation, then we would no longer have 
the property that

   uncurry (</>) (splitFileName  x) == x      (*1)

I don't actually care about the details here as long as we have a story 
that is reasonably consistent.  My main concern is that

   isValid x  =>  isValid (takeDirectory x)

the lack of which is the main problem with the current formulation, as 
you (Duncan) mentioned above.

Perhaps we should drop the magic normalisation that </> does, and apply 
the normalise function to both sides of (*1).  There would probably be a 
bunch more properties that would have to change too, I'm guessing that 
normalise would proliferate.

Incedentally, I dislike the way that trailing slashes are treated in the 
current filepath implementation.  A trailing slash is significant in POSIX:

$ ls -l foo
lrwxrwxrwx 1 simonmar GHC 15 2009-09-23 14:04 foo -> /does/not/exist
$ ls foo
$ ls foo/
ls: cannot access foo/: No such file or directory

The path with the trailing slash dereferences a symbolic link, and may 
fail if the link points nowhere.

I think trailing slashes should be dropped by splitFileName.


More information about the Libraries mailing list