
On 18 January 2005 00:27, Ben Rudiak-Gould wrote:
Marcin 'Qrczak' Kowalczyk wrote:
Convenience. I'm worried that it uses separate types for various kinds of streams: files, pipes, arrays (private memory), and sockets. >Haskell is statically typed and lacks subsumption. This means that >even though streams are unified by using a class, code which uses >a stream of an unknown kind must be either polymorphic or use >existential quantification.
Yes, this is a problem. In my original proposal InputStream and OutputStream were types, but I enthusiastically embraced Simon M's idea of turning them into classes. As you say, it's not without its disadvantages.
I recognised this problem, which is why TextInputStream and TextOutputStream are existential wrappers around streams. Most clients will be using the Text streams, so they won't suffer from the polymorphism problem. However, we could also provide a non-overloaded version using one of Ben's solutions:
I see several possibilities here.
* We could adopt Avery Lee's suggestion (from the discussion in 2003) to use field labels instead of methods. Advantages: InputStream and OutputStream behave more like their OOP equivalents, with no loss of extensibility. Disadvantages: potentially less efficient (no specialization possible); loses some static type information.
Unfortunately GHC isn't nearly as good at optimising records as it is at optimising type class overloading. Of course, type class overloading is just a special case of polymorphic records, but there you go.
* We could use a single type for all input and output streams in the standard library, but retain the type classes also.
* We could provide existential wrappers:
data IStream = (InputStream a) => MkIStream !a instance InputStream IStream where ...
This one gets my vote. BTW, Marcin: the library in the prototype implementation differs somewhat from the version of the interface in the Haddock docs. The docs were written before I started hacking on the prototype. Cheers, Simon