[Haskell-cafe] RE: ANN: System.FilePath 0.9

Bulat Ziganshin bulat.ziganshin at gmail.com
Wed Jul 26 15:25:12 EDT 2006

Hello Duncan,

Wednesday, July 26, 2006, 7:34:50 PM, you wrote:

>> Exactly.  I believe, a FilePath should be an algebraic datatype.
>> Most operations on that don't have to be specified, because they are
>> simple and have an obvious effect.  Add a system specific parser and a
>> system specific renderer, maybe also define a canonical format, and the
>> headaches stop.  What's wrong with this?

> We've had this discussion before. The main problem is that all the
> current IO functions (readFile, etc) use the FilePath type, which is
> just a String. So a new path ADT is fine if at the same time we provide
> a new IO library. That of course is an ongoing discussion in itself.

i don't agree. as i said earlier today, the IO library by itself contains
only a few FilePath-related functions. actually, there is only one
basic function that accepts FilePath - fdOpen, and about 10 (in my
current design) that calls it directly or indirectly. also there is
'show' function that should show filename. that's all. most part of
library don't deal with filenames completely - be it hPutChar, hSeek
or hFlush functions, so i can say that it's not great problem

moreover, we can't switch all the things simultaneously, so we should
provide emulators of new behavior which uses old decisions internally.
for example, you can include in FPS library readFile function that
accepts class but converts it to just a string for using with existing
System.IO.fileOpen. in some future this implementation can de changed
to "real" one using appropriate Streams.fdOpen, for example:

readFile :: (FilePathClass f) =>  f -> IO ByteString
readFile f = bracket (openFile (FilePathClass f) ReadMode) hClose
    (\h -> hFileSize h >>= hGet h . fromIntegral)

of course, this don't make much sense, it's just an example

really, filenames are mainly involved in System.Directory module. so,
i propose:

1) include Stringable class in FPS lib, if possible
2) convert the FilePath module to use this class operations
3) make variant of System.Directory which uses this ADT and fucntions
from FilePath module
4) move my Streams library to darcs and change fdOpen and File.show
functions so they use the FilePathClass

> So until we have the opportunity to change the FilePath type there does
> seem to be value in providing a library that takes some of the
> complexity and portability nightmares out of using the existing FilePath
> type.

i think, we have such opportunity

>> data FilePath = Absolute RelFilePath | Relative RelFilePath
>> data RelFilePath = ThisDirectory 
>>                  | File String
>>                  | ParentOf RelFilePath 
>>                  | String :|: RelFilePath
>> parseSystemPath :: String -> Maybe FilePath
>> renderSystemPath :: FilePath -> String
>> We can even clearly distiguish between the name of a directory in its
>> parent and the directory itself.  On Windows, the root directory just
>> contains the drive letters and is read-only,
>> drive-absolute-but-directory-relative paths are simply ignored (they are
>> a dumb idea anyway).  Seperator characters are never exposed, all we
>> need now is a mapping from Unicode to whatever the system wants.

i don't think the FilePath type is really required. imho, it should
be enough to convert between various filepath-representing types.
these types should include string, bytestring and system-specific
type, if needed:

class FilePathClass f
instance FilePathClass String
instance FilePathClass ByteString
instance FilePathClass Word16String  -- for windows

cvtFilePath :: (FilePathClass f1, FilePathClass f2) =>  f1 -> f2

functions reading directories will return system-specific filenames
representation, i.e. on windows:

getDirContents :: IO [Word16String]

FilePath module should work over any FilePathClass instances, so it
can be used to construct filepaths from pieces and so on. then these
filenames represented as Word16String values can be used to open
files, create directories and so on. if one need to show filename or
convert it to some system-independent format (say, for serialization),
he should use cvtFilePath function

> That's another portability headache - file name string encodings.
> Windows and OSX use encodings of Unicode. Unix uses strings of bytes.
> They are not fully inter-convertible. On Unix the traditional technique
> is to keep a system file name in the original encoding and convert to
> Unicode to display to the user, but the Unicode version is never
> converted back to a system file name because it doesn't necessarily
> convert back to the same sequence of bytes.

> My point is it's not quite as simple as "just making an ADT".

Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com

More information about the Haskell-Cafe mailing list