[Haskell-cafe] Restricted type classes

John Lato jwlato at gmail.com
Mon Sep 6 11:11:33 EDT 2010


>
>
> Message: 20
> Date: Sat, 04 Sep 2010 03:40:49 -0400
> From: wren ng thornton <wren at freegeek.org>
> Subject: Re: [Haskell-cafe] Restricted type classes
> To: Haskell Cafe <haskell-cafe at haskell.org>
> Message-ID: <4C81F801.606 at freegeek.org>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> On 9/3/10 12:16 AM, Ivan Lazar Miljenovic wrote:
> > 2) How far should I go?  Should I restrict myself to the
> > "data-oriented" classes such as Functor, Traversable, etc. or should I
> > try to make restricted versions of Applicative and Monad?  Assuming I
> > should:
>
> I'd say you should do as much as seems reasonable. I tend to take things
> as far as I can, but that'd end up doing a lot of the same work as
> category-extras. For a general collections library, I think it'd make
> sense to try to keep things simpler than that if possible. The simpler
> it is, the better the uptake will be, so long as it's still complex
> enough to capture what it needs to.
>
> I'd say you should include: Functor, Foldable, Traversable, Pointed,
> Applicative, Monad, and Monoid (both additive and multiplicative in
> separate classes, as in the monoids package). Those eight make for a
> really comprehensive toolkit that does most of the things people
> frequently need. Of course, not every collection will have instances for
> all of them.
>

Although I agree these do most things that people need, it's very rare that
I need a data structure that guarantees *only* these features.  Most often I
need a map, a queue, etc. because I need either lookup by key, queue
properties, etc.  I think it's necessary to include classes like Indexable
and Queue.  Indexable may need to be split into two, one for ordered-Int
indexes (i.e. lists) and one for Maps.  Just a few days ago I wanted to
change the priority queue implementation in some code.  This was painful
because the different available implementations all have varying APIs, so I
couldn't just change the imports.  I've wanted to do this in other contexts
as well (e.g. maps and tries).

The perhaps more important use is for coding algorithms that depend upon map
properties, queue properties, etc., but leaving the actual implementation
polymorphic so it can be chosen by a higher level.

If the purpose of this project is to present a common interface for
containers, then I think you should start by seeing what are the most common
containers (I would guess lists, sets, maps, and queues) with a goal of
providing their specific functionality through classes.  Then all the common
stuff can be stripped out and provided by superclasses.  Of course we
already know a great deal of the common operations, e.g. Traversable and
Foldable, and we make use of those abstractions.  It's this last step of a
common map interface, queue interface, etc. that's missing.

If you're just going to provide stuff we already have, I don't really see
the point.


>
> > 2c) Should I keep the classes as-is, or should I explicitly put in the
> > constraints mentioned in the Typeclassopedia (e.g. make Applicative an
> > explicit superclass of Monad, and define return = pure for
> > compatability reasons)?  If so, should I bring over Pointed, etc. from
> > category-extras to round out the set or just stick with classes that
> > are already in base?
>
> If you're defining a new hierarchy, I'd say you should do it correctly,
> i.e.
>
>     class                Functor     where fmap
>     class Functor     => Pointed     where unit -- or point
>     class Pointed     => Applicative where (<*>) ; (<*) ; (*>)
>     class Applicative => Monad       where (>>=) ; join
>

Shouldn't it be:

    class Functor where fmap
    class Pointed where point
    class (Functor f, Pointed f) => PointedFunctor f where
    class PointedFunctor f => Applicative f where (<*>); --etc.
    class Applicative f => Monad f where (>>=); --etc.

even I might omit PointedFunctor, though, because it doesn't add anything.
 If it is omitted, that just means your Applicative contexts are slightly
longer.  But please don't make Pointed depend on Functor - we've already
seen that it won't work for Bloom filters.

Cheers,
John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20100906/50259343/attachment.html


More information about the Haskell-Cafe mailing list