Version française
Home     About     Download     Resources     Contact us    
Browse thread
Polymorphic Variants
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Dirk Thierbach <dthierbach@g...>
Subject: Re: Fwd: [Caml-list] Polymorphic Variants
[Please don't reply directly to me AND to the list, just to the list
is enough. Thanks.]

On Fri, Jan 19, 2007 at 11:35:36AM +0100, Tom wrote:
> On 19/01/07, Dirk Thierbach <dthierbach@gmx.de> wrote:

> Well, in some sense, generic value overloading is somewhat like Haskell's
> type classes, 

Yes. That's exactly what type classes are for -- overloading of functions
(including infix operators).

> Prelude> :t \x -> x
> >\x -> x :: forall t. t -> t
> >
> >Prelude> :t \x -> x * x
> >\x -> x * x :: forall a. (Num a) => a -> a

>     forall a . (int, float, complex, fraction, bignum, int32, vector2,
> vector3, string) => a -> a

That's both longer and not extensible -- what if you're going to link
a module the offers matrices? Don't you also want to use the function
in that context?

> or, what I would prefer:
> 
>     [int -> int | float -> float | complex -> complex | fraction ->
> fraction | bignum -> bignum | int32 -> int32 | vector2 -> vector2 | vector3
> -> vector3 | string -> string]

That's even worse :-)

> (Yes, it seems a lot of writing... but remember that it is not you who
> writes that, it's the compiler. While for such short types, a -> a,
> Haskell's notation is better, it could become hard to understand with more
> complex types:

>     forall a . (float, complex, fraction) => forall b . (int, string) => a
> -> a -> b -> b -> (a, b)

> Now, go figure all the possibilities... It's much simpler when the compiler
> lists all the combinations for you.

And that's exactly what the Haskell compiler does (see below). BTW,
the important thing is the type variable after the predicate, just
ignore the forall's for the moment. So the above type is nonsense, a
possible example type could look like:

(Num a, Floating b) => a -> a -> b -> b -> (a, b)

And it's quite easy to read: The function itself has type 

a -> a -> b -> b -> (a, b)

where all the a's represent the same type, and all the b's represent
the same type, as usual in type inference. Moreover, every concrete
type for "a" must be an instance of Num (i.e., float, complex,
fraction, whatever, you don't care -- the important point is that it
is "a number"), and "b" must be a instance of Floating (same idea).

> >Hell, I want to overload 0 to mean 0, 0., 0. + 0.i, zero vector and
> >> the zero matrix.
> >
> >No problem either: Number literals like "0" are translated into the
> >expression "fromInteger 0", so by overloading fromInteger in the
> >type class, you can generate the apropriate constant.

> Can Haskell overload values? And functions by their return type?

It can overload integer and fixed point literals (in the way described
above). It cannot overload any other "values" (whatever that should
be :-). And yes, it can overload functions by their return type:

Num a => Integer -> a

is a legal type (for example, it's the type of the function "fromInteger"). 
It really doesn't matter if the type variable "a" appears as argument
or as the result (or, more generally, in a covariant or contravariant
position).

If you want more details, I'd recommend to have a look at the Haskell 
docs or tutorials.

- Dirk