caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Alain Frisch <frisch@clipper.ens.fr>
To: Clemens Hintze <cle-ocaml@qiao.in-berlin.de>
Cc: Mark Wotton <mrak@cs.usyd.edu.au>, Caml list <caml-list@inria.fr>
Subject: Re: [Caml-list] Re: [Q]: Co(ntra)variance and subtyping?
Date: Sun, 18 Nov 2001 14:18:10 +0100 (MET)	[thread overview]
Message-ID: <Pine.GSO.4.33.0111181304140.27347-100000@clipper.ens.fr> (raw)
In-Reply-To: <20011118101636.A38485@qiao.in-berlin.de>

On Sun, 18 Nov 2001, Clemens Hintze wrote:

> - If you believe that contravariance isn't generally particularly
>   useful, as you stated in the mail before, why can I flag some type
>   with (-'a) stating this is contravariant? What sense does this make?

> - What exactly are types and subtypes in OCaml? You know, I am coming
>   mainly from the imperative world. There I use languages that makes
>   no distinction between classes and types. Is 'int' a subtype of
>   'float'? How can I decide if something is a subtype of another one?
>   I do not ask in sense of OO inheritance but in OCaml terminology.

If you don't do OO, you can live with OCaml without knowing what 'subtype'
means.

Types in Caml are syntactical expressions, whose full syntax is
given in section 6.4 of OCaml user's manual. As types may contain type
variables, there is a natural order 'less general' induced by
instantiating type variables. The type inference algorithm allows to
take instances, that is to use an expression of a more general type where
a less general type is expected. (this is an unaccurate description of the
algorithm).

What about objects ?  Let's have a look at:

# let f x = (x # value) + 1;;
val f : < value : int; .. > -> int = <fun>

The function f accepts any object with a method value (returning an int)
and possible others: the ".." really denotes a type variable that can
be instantiated to a row of other methods.

# class o = object method value = 2  method str = "abc" end;;
class o : object method str : string method value : int end
# f (new o);;
- : int = 3

Here ".." is instantiated with (str : string). This kind of type matching
allows to use objects with extra methods in a context that expects only
some methods. More precisely, it is the context that accepts more methods.

What you can't do with that is for instance:

# class o = object method x = 2  method y = "abc" end;;
class o : object method x : int method y : string end
# class p =  object method x = 3 end;;
class p : object method x : int end
# [new o; new p];;
This expression has type p = < x : int > but is here used with type
  o = < x : int; y : string >
Only the second object type has a method y


A list in OCaml is homogeneous: all the elements must have the _same_
type; you could say that [new o; new p] has type < x : int; .. > list,
but then ".." has to be unified with (y : string) and ()  [the empty
row of methods], which is impossible.

Here you have to help the type system, and coerce both objets
to a common supertype:

# type t = < x : int >;;
type t = < x : int >
# [(new o :> t); (new p :> t)];;
- : t list = [<obj>; <obj>]

Coercing to a supertype amounts to forget some methods (which is safe,
but never done automatically).

Now there is a subtyping relation on object types. But it is handy to have
it also on constructed types:

# let l1 = [new o; new o] and l2 = [new p; new p];;
val l1 : o list = [<obj>; <obj>]
val l2 : p list = [<obj>; <obj>]
# (l1 :> t list) @ (l2 :> t list);;
- : t list = [<obj>; <obj>; <obj>; <obj>]

To make l1 and l2 compatible, we again use a coercion, but now, we use
the subtyping relation over lists:  "o list is a subtype of
t list _because_ o is a subtype of t". This express the covariance
of the list type constructor.

Some constructors are contravariant. For instance, the arrow constructor
t->s is contravariant in t and covariant in s. This means that:
t1->s1 is a subtype of t2->s2 if and only if t2 is a subtype
of t1 and s1 is a subtype of s2. If the arrow constructor was
considered covariant in both arguments, it would be easy to break
the type system (runtime type error) with a coercion.


And some constructors are invariant, such as:
type 'a inv = A of 'a | B of 'a -> unit

t1 inv is a subtype of t2 inv if and only if t1 and t2 are equal
(modulo the subtyping relation).


Now, if you don't have the definition of a type constructor - say
it is an abstract type from your point of view -
you can't tell what its variance is w.r.t one of its arguments.
So OCaml allows to specify this information in module interface;
for instance, in map.mli:

module type S =
  sig
    type key
          (* The type of the map keys. *)
    type (+'a) t
          (* The type of maps from type [key] to type ['a]. *)
...


The '+' means that type t is covariant: a map from type key to type
t1 can be coerced to a map from type key to type t2 if and only
if t1 is a subtype of t2.

(I don't know why other modules such as Queue do not give variance
information ...)


So, the subtyping relation is only raised from object types to
all types using variance information for each type constructor
(actually, subtyping can also appears with polymorphic variants).
There is no subtyping between basic types: int is not a subtype of float.

One reason for it is that in OCaml, coercion to a super type does not
require any computation, thanks to the concrete representation of objects.
So coercing a list does not involve walking through all its elements.
As int representation is not compatible with float one, int is not a
subtype if float.



-- 
  Alain

-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


  reply	other threads:[~2001-11-18 13:21 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-11-16 19:37 [Caml-list] " Clemens Hintze
2001-11-17 14:18 ` Mark Wotton
2001-11-17 14:55   ` Mark Wotton
2001-11-17 17:50   ` [Caml-list] " Clemens Hintze
2001-11-17 23:17     ` Mark Wotton
2001-11-18  9:16       ` Clemens Hintze
2001-11-18 13:18         ` Alain Frisch [this message]
2001-11-19  9:54           ` Remi VANICAT
     [not found]       ` <9t7v4d$gij$1@qrnik.zagroda>
2001-11-18 11:57         ` Marcin 'Qrczak' Kowalczyk
2001-11-18 13:34 ` [Caml-list] " Andreas Rossberg
2001-11-18 21:22   ` Pixel
2001-11-19  0:33     ` Jacques Garrigue
2001-11-18 22:35       ` David Gurr
2001-11-19  7:24         ` [Caml-list] " Clemens Hintze
2001-11-19 12:03           ` Markus Mottl
2001-11-19  8:29         ` [Caml-list] " Xavier Leroy
2001-11-19 11:03       ` Alain Frisch
2001-11-20  9:58         ` Didier Remy
2001-11-19 11:14       ` Pixel
2001-11-18 22:30   ` [Caml-list] Re: variance, subtyping and monads... oh, my! james woodyatt
2001-11-19  8:11     ` Francois Pottier
2001-11-19  9:02       ` james woodyatt
2001-11-19  9:58         ` Markus Mottl
2001-11-19 20:47           ` james woodyatt
2001-11-19 12:56       ` Frank Atanassow
2001-11-19 10:39     ` Andreas Rossberg
2001-11-19 12:21       ` Markus Mottl
2001-11-19 13:43         ` [Caml-list] Kylix and OCaml Christophe Raffalli
2001-11-20  2:05           ` Vitaly Lugovsky
2001-11-20  8:51             ` Christophe Raffalli
2001-11-22  1:42               ` Vitaly Lugovsky
2001-11-20 10:00             ` Benjamin Monate
2001-11-20 10:24               ` [Caml-list] [Bug in an interface between C++ and OCAML due to some pointer encapsulation] Sylvain Kerjean
2001-11-20 12:14             ` [Caml-list] Kylix and OCaml Maxence Guesdon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.GSO.4.33.0111181304140.27347-100000@clipper.ens.fr \
    --to=frisch@clipper.ens.fr \
    --cc=caml-list@inria.fr \
    --cc=cle-ocaml@qiao.in-berlin.de \
    --cc=mrak@cs.usyd.edu.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).