
Hello, On Jan 27, 2005, at 10:46 AM, Krasimir Angelov wrote:
Hello Guys,
Let me propose another solution which is simpler (at least from my point of view)and will not break the existing. When I designed the API of the original System.FilePath library I looked at OS.Path modules from Python and ML. They both uses plain string to keep the file path but does precise parsing/printing of the path when it is manipulated. I haven't ever heard of any language that uses special FilePath type instead of plain string. I don't want to do any parsing/printing each time when I need to open file or create directory. In most cases the file path is passed as string from the outside world to the application and if we have special FilePath then we need each time to parse it. What I propose is the following:
Actually, Common Lisp specifies a special data type to handle logical filepaths, which are distinct from file path strings. Having had to debug common lisp code that uses this (written by other people) I've observed that this attempt to do the "Right Thing" almost certainly has caused more trouble than it has solved. While an abstract filepath isolates you from having to deal with the syntax of file paths on different systems, it does not provide an abstract view of the filesystem hierarchy. These differ greatly, even among unix-like systems. Handling differences in the file system hierarchy inevitably results in a lot of system specific code, for any program that has to use files scattered across a system.
- Keep the existing System.IO API the same. openFile, createDirectory ... will take the file path as string. - Introduce two new modules System.Posix.FilePath and System.Win32.FilePath. Each of them will provide functions for parsing/printing of paths to/from some platform specific type: PosixFilePath and Win32FilePath. As you can see from Robert Dockins examples, these types can be completely different. - Introduce third module System.FilePath which will do some basic operations of path through parsing/printing. The API of this module can be similar to this which I wrote but its implementation can be more accurate if it works on some ADT instead of string. The module will use #ifdef in order to import the right from the above two modules.
In most cases we do only simple manipulations on path and I don't think it is required and easy to explicitly parse/print the path only in order to change its extension. I prefer to invoke changeFileExt and don't care how the function will do its job. If someone would like to perform any more complicated operations on file path he can import the system specific module and use PosixFilePath or Win32FilePath. This is basically the way in which OS.Path is implemented in ML.
Your proposal above for a lightweight solution seems the right way to go. If there is really a need for a higher layer it could be built upon something like you suggest. One thing that the library shouldn't exclude is the manipulation of non-native file paths. For example, I on my unix system I may want to generate a win32 file path as part of some code that will be executed on Windows machine. The underlying os-specific modules should always be available, even if there is a module for file path manipulations specific to the host-OS. (If I understand correctly, this is what you've proposed with the System.FilePath.)
The type class solution doesn't work very well. As Simon said it may require to have #ifdef-s in some places in order to choice the right type. Another disadvantage is that this will complicate some data types. Example:
data FilePath a => MyFileInfo a = MyFileInfo { path :: a; size :: Integer }
I don't want to add extra type parameters here only in order to specify the right FilePath type.
Cheers, Krasimir _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Best Wishes, Greg