[m-dev.] for discussion: stream library v2
Peter Ross
peter.ross at miscrit.be
Tue Sep 26 20:24:56 AEDT 2000
On Tue, Sep 26, 2000 at 05:10:01PM +1100, Tyson Dowd wrote:
> On 25-Sep-2000, Peter Ross <peter.ross at miscrit.be> wrote:
> > > >
> > > > I think that the low level interface has to be impure
> > >
> > > Why?
> > >
> > because of the way it is defined. We define the type class method to read
> > one character as follows
> >
> > :- impure pred read_char(Handle::in, Char::out) is semidet.
> >
> > This has to be impure because the implementation may be changing the
> > external state of the world, it may also not be but we have to assume
> > the worst.
> >
> > I for the life of me can think of a way to get around this in a clean
> > and elegant manner.
>
> I think the problem is that while the lowlevel impure interface is
> fine for going straight to foreign language implementations, it should
> not be the only way to implement a stream.
>
> If I want to use the Mercury "string" type to implement string streams,
> I should be able to do so in a pure manner. That is, I should be able
> to be an instance of some stream interface that doesn't rely have the
> word "impure" in it anywhere.
>
> :- begin_wild_speculation_without_testing.
>
> Perhaps the best way to do this is by having a second set of type
> classes (we'll call them highlevel streams) that are intended for
> implementing streams using pure building blocks. The methods would all
> be pure and use di/uo moded stream pairs.
>
>
> :- typeclass highlevel__output(S) where [
> pred highlevel__output(char::in, S::di, S::uo) is det
> ].
>
> The predicates that go here are basically the same as the ones in
> stream.m (maybe a little bit different because they don't have to worry
> about putback).
>
> Any lowlevel can be an instance of highlevel -- just use a wrapper.
>
> :- type lowlevel(T) ---> lowlevel(T).
>
> :- instance highlevel__output(lowlevel(S)) <= lowlevel__output(S) where [
> (highlevel__output(Chr, lowlevel(Stream), lowlevel(StreamOut)) :-
> ( impure lowlevel__write_char(Stream, Chr) ->
> true
> ;
> semipure Err = lowlevel__error_message(Stream),
> throw(stream_error(Err))
> ),
> StreamOut = Stream
> )
> ].
>
> The implementation of this might be different, whatever you decide as
> the implementation of stream__write_char is basically the code that goes
> here.
>
>
> When you create a stream, if it uses the lowlevel interface to satisfy
> stream, you need to create a wrapped version.
>
> :- instance lowlevel(tcp).
> :- instance lowlevel__input(tcp).
> :- instance lowlevel__output(tcp).
> :- instance lowlevel__duplex(tcp).
>
> :- type tcp_stream == lowlevel(tcp).
>
> Now tcp_stream is a member of highlevel. Note the wrapper is single
> argument, single functor, so it won't actually involve an allocation.
>
Your a smart boy Tyson, you should consider doing a phd or something.
I will have a go at implementing this interface, but it looks to have
the best of both worlds to me (assuming it works).
Pete
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list