[Haskell-cafe] I/O interface

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Mon Jan 17 12:12:31 EST 2005


On Mon, 2005-01-17 at 16:27 -0800, 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 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.

I've often thought it would be nice to have a class and it's most
general instance, a record with the same fields as the class has
methods. It would be even better if they could share the same name, eg:

class IStream s where
  read :: s -> ...

data IStream = IStream {
    read :: ...
  }

instance IStream IStream where
  read s = read s --the field selector not the class method

Obviously each instance of the IStream class can be converted to an
IStream record (loosing type information) which is useful for
heterogeneous collections of streams, and other "interface programming"
techniques.

This technique is perhaps a middle ground, it's a tad more complex that
just having a single type for streams but it allows code which does not
want to know to use a single type while allowing for static typing in
other cases where it is desired for safety or for better performance by
specialising.

A downside (apart from naming issues) is that while there is an
automatic conversion IStream data type -> IStream class instance, there
is no automatic conversion the other way round. Compare this with Java
interfaces for example, a Java IStream interface is like our IStream
data type, but there is automatic conversion from the types implementing
the interface to the interface type itself. In Haskell we normally go
for the more strongly typed interfaces (Haskell classes) rather than the
more dynamic interfaces (record of functions) so the language supports
the former more naturally than the latter (eg automatic 'conversion'
when accessing an object through a class interface).

Duncan



More information about the Haskell-Cafe mailing list