Bulat Ziganshin
<[EMAIL PROTECTED]>
writes:
> > Yes - you've reiterated Wadler's original design, with
> > an automatic problems with equational reasoning raised
> > by this approach.
> 
> ok, i can live without it. i mean reasoning :)

That's probably not good, but I don't follow that problem
yet.  I'm afraid I've not had the stamina to follow this
thread properly, and I doubt if I'll get any more stamina
soon, so let me make a proposal not too disimilar to Bulat's
and just hope that people find it appealing enough to flesh
it out.

The idea I'm presenting is simple enough: allow data
constructors as members of classes.  (Sure, David, this does
have the problem of hiding potentially expensive operations
as straightforward pattern matches, but that's abstraction
for you). So

class Sequence s where
   (some other stuff)
   Cons:: a -> s a -> s a
   Nil:: s a

Here Cons and Nil both stand for two things: a constructor
and a deconstructor. The question is how to specify the
values of the two parts when giving an instance. The easiest
way is just to give it in terms of something that already
has the two aspects:

instance Sequence [] where
    ...
    Cons = (::)
    Nil = []

And so a definition like

f Nil = ...
f (Cons a l) = ...

gets a type like Sequence s => s a -> ...

But we also want it to work for cases where the type we are
viewing doesn't already have a constructor that does what we
want, such as giving a list instance for another member of
Sequence:

class Sequence s where
   Snoc:: s a -> a -> s a
   (some other stuff)

The idea here would be to announce that all data
constructors really do have two parts and they are accessed
via qualified names. So the Snoc part of the list instance
would look like this:

   ...
   Snoc.construct l x = l ++ [x]
   Snoc.deconstruct f g [] = g
   Snoc.deconstruct f g l = f (init l) (last l)

(We can of course argue about the precise type used for
deconstructors and there is endless bikeshed painting to be
done for the names construct and deconstruct, but I hope
this gives the general idea).


I think this proposal is simpler than the earlier ones
presented -- enough that someone in better shape than me
could work out the details and implement it. There's no
exciting new syntax, just an extension of some current
syntax to a new area, and functions declared using a "view"
are automatically overloaded for everything that shares the
view.  As far as equational reasoning goes, I think the
approach would be to specify what laws Foo.construct and
Foo.deconstruct have to follow to preserve it, and leave
them up to the programmer to respect (in the same way that
the monad laws aren't tested by the compiler).

-- 
Jón Fairbairn                                 [EMAIL PROTECTED]


_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime

Reply via email to