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

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Jacques Garrigue <garrigue@m...>
Subject: Re: [Caml-list] polymorphic method.
From: Guillaume Yziquel <guillaume.yziquel@citycable.ch>
> By the way, I do not exactly understand the "you might end up with
> types more polymorphic than you expected" part.

This is actually the main problem.
At some point, I actually considered generating automatically
polymorphic method types where possible.
The idea would be simply to first give all the methods in a class
monomorphic types (to avoid the undecidability of polymorphic recursion), 
and then generalize all type variables that do not "escape": i.e. do
not appear in class parameters, value fields, or global references.
Technically this is perfectly doable.
Theoretically, there are problems with principality, as there is no
most generic type for a polymorphic method (all types are incompatible
with each other).
It is easier to see that on a practical example.
Say that I defined lists:

class ['a] cons x l = object (_ : 'self)
  method hd : 'a = x
  method tl : 'self = l
end

class nil = object
  method hd = raise Empty
  method tl = raise Empty
end

Now, both cons and nil would be typable (cons is already typable), and
the inferred types would be:
class ['a] cons : 'a -> 'b ->
  object ('b) method hd : 'a method tl : 'b end

class nil : object
  method hd : 'a
  method tl : 'b
end

At first glance, it seems that the type of nil being completely
polymorphic, we could pass it as second argument to cons.
However, it is not the case. cons has two monomorphic methods, while
nil has two polymorhic methods, and their types are incomparable.
If we look at object types,

type 'a cons = < hd : 'a; tl : 'b > as 'b
type nil = < hd : 'a.'a ; tl : 'b.'b >

Of course, you could argue that what is wrong is the definition of
nil. But basically there is no way to decide what is the right type
for nil as soon as we allow inferring polymorphic methods.

Interestingly, currently you can define nil as an immediate object
and have immediately the right type without any annotation:

exception Empty
let nil = object
  method hd = raise Empty
  method tl = raise Empty
end ;;
val nil : < hd : 'a; tl : 'b > = <obj>

let l = new cons 3 nil ;;
val l : int cons = <obj>

So, the current approach is to privilege the monomorphic case,
requiring type annotations for the polymorphic case. Your suggestion
of allowing to give a hint that you want a polymorphic type makes
sense, but it does not say which polymorphic type: there might be
several, with different levels of polymorphism, with no way to choose
between them. Probably it would be ok to choose the most polymorphic
one, but one can always find counter-examples. So the meaning of your
"polymorphic" keyword would be: "give me the most polymorphic type for
this method, I hope I understand what it will be, but if I'm wrong and
it breaks my program I won't complain". This may be practically ok,
but this is a hard sell as a language feature. Particularly when you
think that future versions of the compiler may be able to infer more
polymorphic types, thanks to improvements in type inference, and
suddenly break your program.

Jacques Garrigue