
Hello Udo, Saturday, November 25, 2006, 4:34:21 AM, you wrote:
the same function, in polymorphic way:
splitToBaseExt :: FilePathClass fp => fp -> (fp,fp)
this change in interface would be indistinguishable for 99% of us.
Err, no. 99% of us _don't_ write flawless programs. With every overloaded symbol you get worse error messages. Have you ever used C++? Ever got a screenful of completely incomprehensible gobbledygook because you forgot a namespace qualification somewhere? Go ahead with all these FooLike and BarAble classes and you get the same from Haskell (and then some, including exponential runtime of the type checker).
you shouldn't mix C++ template system with Haskell classes. C++ can't check templates at the time where template defined that leads to too late error messages. just imagine that improper definition of 'sum' will barks on each call site with a message that you can't use (&&) on Ints. and complex types in such messages is just because templates *don't* use C++ class system with its abstraction ability and the whole type structure shows up in the message if you want to argument against my idea, it's better to find situation where Haskell classes bite you (and stop rely on false assumption that something that is like C++ is automatically bad)
Pathnames are short strings. No need to optimize for performance, instead optimize for clarity.
let's say that 99% of programs don't need any optimization at all. so there is no need in ByteString, Int and other stupid types. stop polymorphism and use BigDecimal for any numeric data! :) functional programming is widely recognized as strong but slow approach. while now anyone who need to write efficient program will probably select C++, things changes and we wrote more and more efficient libraries - be it for integers, strings, arrays or pathnames. I've broken the rule that archivers (like zip) should be written in C++ and developed one with Haskell. in order to make this program efficient, i've written several general-purpose libs that don't existed before - such as serialization or packed string ones, or I/O using unicode filenames so, now i have a code that allows to write efficient programs dealing with a very large number of files. next, Unix/Win works with utf8/utf16 encoded filenames. so, efficient program should use natural filename representation instead of converting to/from String while we can develop a series of libraries that works with filenames represented as Strings, UTF8 ByteStrings and so on, i think the right way is to have one FilePath library that uses operations of some typeclass. as long as you don't argue for restricting monad libraries to IO monad, array libraries - to boxed arrays and numeric libraries - to Integer, you should agree that functionality required only by *some* developers, makes error messages more complex for the rest moreover, i think that Haskell now is the best language for system programming, such as developing mailer daemon, gaming server, or transaction system. but lack of efficient networking, I/O and data structure libraries makes development of system software sort of do-it-yourself task
An algebraic datatype reflecting the algebra of filenames would likely be even more clear, but defining a type class just to support different encodings is definitely overengineering and very likely a bad idea. Remember, this ends with std::basic_ios< char, std::char_traits<char> > or worse.
yes, types are complex nowadays :) you should look into my Streams library which includes such type of beasts. it uses class-based, multi-layered design in order to provide wide set of operations on wide set of stream types with wide set of optional modifiers (such as Char encoding or inter-thread locking). type classes allows here to split functionality into smaller manageable pieces, that can be easily replaced with 3rd-party libs. can you propose alternative design that allow the same flexibility with a less cluttered type names? i think no. the good news for you is that Haskell can infer types and constraints so using very complex types don't need a tons of type constructors as in C++ complex type names reflects *factorizing* of functionality and that is the C++ templates idea that i reused in my Streams lib. instead of defining a lot of independent getByte operations for each possible stream type, i use a class here, and this allows the next, serialization level, to work with any stream. i think that type classes are underweighted in Haskell community because it's not classical FP technique, and while we can't live without standard classes, we develop too small number of our own ones. or at least, not in all areas. besides of Monad or IArray classes, we should think about collection classes (for which Stringable is just a very partial case) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com