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

Ben Moseley ben_moseley at
Sat Nov 14 12:50:19 EST 2009

On 14 Nov 2009, at 14:02, Duncan Coutts wrote:
> So the type distinctions you are making are:
>      * whether a path refers to a file or to a directory
>      * whether a path is relative or absolute

Yep, that's the idea.

> By relative and absolute it looks like you mean whether it starts with
> the root "/" vs not. So "foo/bar.txt" and "./foo/bar.txt" are both
> considered as relative.


> So in the similar design I was working on, instead of distinguishing
> relative and absolute, I distinguish incomplete and complete. I
> initially started with the relative/absolute distinction and moved  
> onto
> this one. It'd be interesting to see which is most useful in practise.
> What I mean by complete is a path referring to an actual file/dir that
> you could pass to a system call. This means they are anchored to some
> point the system knows about, such a "." the current directory or  
> "/" or
> "C:\".
> Then an incomplete path is one that is not anchored. Incomplete paths
> become complete by </> them to a existing complete one (including the
> current dir).
> So the difference between this complete/incomplete notion and
> relative/absolute is for paths that are relative to the current
> directory.
> You would say "Main.hs" :: RelFile
> and
> readFile :: AbsRelClass ar => FilePath ar -> IO String
> and so readFile "Main.hs" is ok, and reads the file "./Main.hs" in the
> current directory.
> I would probably say, "Main.hs" :: IncompleteFilePath
> (though I think I used somewhat shorter type names than that!)
> and
> readFile :: CompleteFilePath -> IO String
> and thus readFile "Main.hs" is not well typed, instead it would be:
> readFile (currentDir </> "Main.hs")
> because that gives us a complete path, and if we want that to be  
> rooted
> at the processes' current directory, then we do so explicitly.

Ah, ok, I see. I can see the attraction to that.

> My intuition with file paths in Cabal, is that this distinction would
> catch more bugs. Ideally cabal's building code would be independent of
> the current directory, but the fact that relative paths get
> automagically completed to being relative to the current directory  
> means
> that it's very easy to break this property.


One possible approach with pathtype as it stands would be a wrapper
module which hides "readFile :: AbsRelClass ar => FilePath ar -> IO  
and exposes it only at the restricted type:
"readAbsFile :: AbsFile -> IO String; readAbsFile = readFile".
This blocks accidental reading of relative files and clients are  
forced to use
something like 'makeAbsoluteFromCwd'.

I don't think this is exactly the same as what you're suggesting (it  
permit the "completion" process to be separated from the reading), but  
I think it
would be a way to catch some of the same bugs?

> There are various other distinctions one could try to make, the  
> question
> becomes which type distinctions are useful and when does it just  
> become
> too much.

I think this is a very important point. It's definitely a balancing  
act. I have
ondered whether even capturing Abs/Rel was overkill, but my current  
(not yet based on much real-world experience) is that it is worth it.



-------------- next part --------------
An HTML attachment was scrubbed...

More information about the Libraries mailing list