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

Simon Marlow marlowsd at gmail.com
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.

http://www.haskell.org/pipermail/libraries/2007-December/008776.html

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
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.


Cheers,
	Simon


More information about the Libraries mailing list