classes

Patrick M Doane patrick@watson.org
Fri, 31 Aug 2001 16:16:59 -0400 (EDT)


On Fri, 31 Aug 2001, Cagdas Ozgenc wrote:

> >class Ord a where
> >   (<) :: a -> a -> Bool
> >
> >data Set a = Ord a => [...]
> >
> >   I don't know if I'm making sense. I'm not that proficient in Haskell
> myself.
> >
> 
> The only thing that bothers me here is the Asymmetry. The syntax treats the
> first, and the second argument differently. Although there is equal emphasis
> on both "a"s in an "<" operation. C++ solves this problem by taking them out
> of the class.
> 
> bool operator < (const Ord& a, const Ord& b);
> 
> where arguments are treated with equal rights. Maybe I am just too
> concerned.

I'm not sure I understand - could you clarify some more? 

> >>Secondly, why does Haskell distinguish between a Type and a Class?
> >>There seems to be no benefit of such approach.
> >
> >   Oh, there's benefit. It does require a serious change in perspective,
> though. It can't be so easily explained.
> 
> One benefit I see here is that I can make the type member of other classes
> afterwards, whereas in C++ you have to specify the base-classes beforehand.
> 
> What again bothers me here that the global functions that are defined over
> the type. Therefore there is a class, but Implicitly!!
> IMHO, a type is actually a class.

If you are familiar with STL terminology, it might be better to think of
Haskell classes as 'concepts'.  Concepts can't be expressed directly in
C++ but are much closer to a Haskell class. A concept describes a set of
rules such as: 

  - What expressions are valid?
  - What are the types of these expressions?
  - What are their semantics?
  - Are there any preconditions/postconditions that must be satisfied?
  - What are their running times?

A Haskell class lets you specify a set of valid expressions and their
types as well as give it a name that can be referred to later. It also
allows you to provide default definitions for some expressions.

For example, let's assume we have some function that operates on a
Container. The C++ definition would look like this:

template <class Container>
void f(Container c) { ... }

but the identifier 'Container' is merely a documentation placeholder and
can't be used by the compiler to provide more useful feedback in the case
of errors.

In Haskell, the type signature of f would be:

  f : Container a => a -> unit

and now the compiler can verify that any value passed to 'f' meets the
restrictions required by the Container class.

Let me know if that makes any more sense (or just confuses the matter!).

Patrick Doane