[Haskell-cafe] Factoring into type classes

Iavor Diatchki iavor.diatchki at gmail.com
Mon Jan 19 13:59:54 EST 2009


Hello,
The multitude of newtypes in the Monoid module are a good indication
that the Monoid class is not a good fit for the class system (it is
ironic that discussing it resulted in such a huge thread recently :-).
   How I'd approach the situation that you describe would depend on
the context (did I design the class, or am I just using it?  am I
writing a library that is to be used by other people, or is the class
just used in an internal part of my program?, etc.) but, in general,
here are some ideas:
1. If one type can be made into an instance of a class in multipe ways
and I have no control over the class:
   - I would provide non-overloaded versions for each implementation
   - if there is a "natural" one (something that is quite commonly
used) I would use it for an instance
   - if most uses are equally likely to be useful, then I would not
provide an instance but just use the non-overloaded functions.  If I
did provide an instance, then I would be careful to document the
choice I made.
2. If I have control over the class I may consider changing it:
  - Consider using a different class, that has operations that are
more specific to what I am doing (e.g., use a PrettyPrint class
instead of Show class)
  - If many types are members of the same classes, then it may be
useful to combine them (i.e., add multiple methods that perform the
different operations).

I think that I have done all of the above in different situations, and
so I don't think that there is a single correct answer.  I usually
avoid using the "newtype" trick as I find it inconvenient:  usually
the newtype does not have the same operations as the underlying type
and so it cannot be used directly, and if you are going to wrap thing
just when you use the class methods, then you may as well use the
non-overloaded operations.

Hope that this helps,
Iavor


On Mon, Jan 19, 2009 at 9:40 AM, Patai Gergely
<patai_gergely at fastmail.fm> wrote:
>> As a side curiosity, I would love to see an example of any data structure
>> which has more than one Functor instance.  Especially those which have
>> more than one useful functor instance.
>
> data Record a b = R { field1 :: a, field2 :: b }
>
> If I want to use fmap to transform either field, I have to declare the
> type to have the corresponding type variable at the end, i.e. choosing
> "Record a b" or "Record b a" is already a design decision, and it is
> driven by the standard Functor class in this case. I can define custom
> functions fmap1 and fmap2 manually, but then I don't get the advantages
> of overloading, like fmapping over a data structure containing my
> records.
>
> Now I understand that I can't get everything, and my question is mainly
> what to do when such a dilemma comes up. Those who have already
> encountered such a dilemma: how did it come up and what did you do to
> solve it?
>
> Gergely
>
> --
> http://www.fastmail.fm - Same, same, but different...
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


More information about the Haskell-Cafe mailing list