[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