[m-dev.] stream typeclasses (again)

Julien Fischer juliensf at cs.mu.OZ.AU
Mon Mar 6 11:05:36 AEDT 2006


On Sun, 5 Mar 2006, Ian MacLarty wrote:

> On 28 Feb 2006, at 08:03, Julien Fischer wrote:
>
> > I've spent a bit more time playing around with the stream typeclass
> > proposal.
> > Attached is the (or at least my) latest version plus a number of
> > example
> > streams.  (Ian, I think you mentioned you'd done some more work on
> > this as
> > well?)
> >
> > Major changes from last time:
> >
> > * The error type is now part of the stream typeclass, (it's
> > functionally
> >   dependent on the stream type).
> >
> > * The close method has been removed (for the moment at least)
> >
>
> I think there may have been a misunderstanding about what the State
> argument of the stream typeclass is for.  It's supposed to be the state
> that is modified when you read or write from the stream, so for the
> buffer stream it would be the string type.

There was no misunderstanding on my end.  The problem that I was trying to
avoid by not making the state the string was the following:

Imagine I create two string buffers, let's call them <<ian>> and <<julien>>.
Associated with each I have two states.  Let's say the initial state for
<<ian>> is Ian0 = "maclarty" and the initial state for <<julien> is Julien0 =
"fischer".  I wrote the buffer type the way I did in order to stop you doing
things like this.

	put(<<julien>>, "abc", Ian0, Ian).

Under the new version of the string buffer there is no connection between
the identity of a stream and its current contents.  This was raised in a
previous post by Doug Auclair, i.e. what do you do when the stream is
the same as the state.  One solution I've been toying with is adding
another kind of stream to the stream hierarchy, something like:

	:- typeclass stream(S) where [].

	:- typeclass input_stream(Unit, Stream) where [
		pred get(Unit::out, Stream::in, Stream::out) is det
	].

	:- typeclass output_stream(Unit, Stream) where [
		pred put(Unit::in, Stream::in, Stream::out) is det
	].

This would allow string buffers of the type you suggest above (it would
also work in contexts that allow backtracking which might be nice for
string buffers).

> I've rewritten the buffer module and attached it.  At the moment it
> doesn't take advantage of the unique modes, so we could make it more
> efficient by doing destructive update of the string with foreign code.
>
> Also I think the encryption typeclass should be implemented
> differently.  Instead of writing to the stream to encrypt the data, and
> then reading from the same stream to get the encrypted data, I would
> add an extra argument to the 'new' predicate that creates the stream.
> The extra argument would be the stream to write the encrypted data to.

The encryption stream example was just an example of a duplex stream.

> Consider the situation where you're implementing an encrypted file
> transfer protocol.  Using your design you'd have to either write the
> whole file to the encryption stream and then read it and forward it to
> a socket stream (which would exhaust memory if the file was big), or
> implement some kind of buffering system that would flush the encryption
> stream to the socket at regular intervals.  Using my proposed design
> you'd just create the encryption stream, giving the socket stream as an
> argument, then everytime you write to the encryption stream the
> encrypted data automatically gets forwarded to the socket stream.
>
> In trying to implement this design though I hit some restrictions in
> the typeclass system which I think probably don't need to be there.
> I'll describe these in a separate email.
>
> I still think the 'name' method shouldn't need to alter the state.
> Perhaps we should do away with that method.  I can't see it being
> particularly useful, since I imagine you'd only use the stream name in
> error messages, which can be done by including the name in the Error
> type for the stream.

You certainly want the ability to print out filenames in other contexts.
`mmc -V' prints out lots of filenames in things that aren't error messages.
I don't see why more general streams would be any different.

I agree the 'name' method shouldn't need to alter the state, but that's
a relatively minor issue.

> Another issue we haven't addressed that we will need to before we
> update the std library is what will the notion of the current stream
> mean?  Since we can't store a general stream in a global mutable (and
> it doesn't really make sense to anyway), should we just have the notion
> of the current *file* stream?

Current file stream is trivial to implement ;-), so I suggest we just go
with that for now.

Cheers,
Julien.
--------------------------------------------------------------------------
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