
ChrisK
Jon Fairbairn wrote:
I currently only get f :: [t] -> something, so if I later discover that I need to change the input representation to be more efficient than lists, I have to rewrite f. Wouldn't it be so much nicer if I could simply add a declaration
f:: Stream s => s t -> something and get a function that works on anything in the Stream class? The core of the idea would be to allow classes to include constructors (and associated destructors) so the definition of Stream would include something for ":" and "[]" and their inverses, though I've no real idea of the details; can anyone come up with a plan?
I had been avoiding adding my two cents, but I must object to this.
Because this is starting to sound like one of the maddening things about C++.
Namely, the automatic implicit casting conversions of classes via their single argument constructors.
Unfortunately I'm not sufficiently familiar with C++ to know what this means. Perhaps you could clarify? Despite the obvious interpretation of my message (ahem), I'm not advocating much that's automatic. In the case of lists I was imagining that they would be the default for Streams in much the same way that Integer is the default for Num. I'd be happy to discard that part of the idea (though I'd expect howls of protest from those who want lists to be ruling class citizens).
What if the 'f' in the quoted message above is itself part of a type class. Then one has to decide which instance 'f' is being called and what constructors/destructors are being called to view the 's t' parameter as the correct concrete type. That way lies madness.
Again, I think the difficulty here is a discrepancy between the interpretation of what I wrote and what I intended to mean :-), viz that classes could (in addition to their usual functions) define constructor/deconstructor pairs that would be used in desugaring pattern matching. I didn't mean that constructors of the same name could appear both in classes and in data declarations. So if one had something like class Stream s where Cons:: a -> s a -> s a Nil:: s a Snoc:: s a -> a -> s a ... {- an instance definition for Stream would have to somehow give both construction and deconstruction functions for Cons and Nil -} then a definition of the form f Nil = ... f (Cons h t) = ... would be unambiguously f:: Stream s => s a -> ... (in the absence of defaulting). There are issues about checking coverage of cases, but I don't think that's the problem you were raising? -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk