[m-dev.] stream typeclasses (again)

Julien Fischer juliensf at cs.mu.OZ.AU
Wed Mar 8 15:03:52 AEDT 2006


On Tue, 7 Mar 2006, Ian MacLarty wrote:

> >> 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).
> >
>
> Ah, I see why you did it like that now.  Do you think this type of
> situation will be a problem in practice?

With string buffers defined this way I can imagine it sometimes being a
problem (or more specifically I can imagine it being a pain to debug if it
ever goes wrong).

An alternative for the string buffer type would be to store store the stream
name with the stream data:

	:- type string_buffer ---> string_buffer.

	:- type string_stream
		---> string_stream(stream.name, string).

	:- instance stream(string_buffer, string_stream).

However this would prevent us from eventually having name/1 as a method (since
for string buffers of this sort the name is stored with the state type not the
stream type).  Alternatively, we could just make it so all string buffers have
the same name, e.g. "string_buffer", but I don't really like that idea because
it would make debugging code that makes extensive use of these things
difficult.

> I can't imagine people would get their julien's and ian's mixed up all that
> often...

Yes, but just imagine the chaos that would ensue if they did ...

> > 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).
> >
>
> Yes, but it has the disadvantage that predicates designed to work with
> other streams won't work with the above streams.  So for example you
> couldn't write xml to a string, unless you implemented two versions of
> write_xml_doc.

Or if we had typeclass reflection.

> Now if we had nested uniqueness and polymorphic modes, then we could
> implement all streams like your suggestion above (since we could embed
> the IO state in the stream type)...

True, although once we get those features we could support the other type
of stream alongside the current one.

> >> 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.
> >
>
> Okay.

I originally had something like this in mind:

	:- typeclass stream.base(Stream) where [
		func(Stream) = stream.name
	].

	:- typeclass stream.stream(Stream, State) <= stream.base(Stream)
		where [ ...

The reason I didn't implement it that way was just that the current io module
is not setup to handle things that way.  I suggest we just go with "state
altering" name method for now and add the function version at a later date.

Are you reasonably satisified with the rest of the design as it stands?

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