caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Why can't I use val mover : < move : int -> unit; .. > list -> unit ?
@ 2001-01-10 12:39 Mattias Waldau
  2001-01-10 19:16 ` Brian Rogoff
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Mattias Waldau @ 2001-01-10 12:39 UTC (permalink / raw)
  To: Caml-List

In the example below I have two separate classes with no common 
super class. Both classes have a method 'move'.

I have no problem using the function main below that can an 
arbitrary 'objects with move defined'. However, when I try to 
expand the example to list of objects with move defined, I 
cannot use this function.

How can I use the function 'mover'? How do I coerce to 
objects with move defined? 

/mattias




(*

let _ = mover [p;q]

This expression has type p1d_1 = < move : int -> unit >
but is here used with type
  p1d_2 = < move : int -> unit; only_here : int -> int >
Only the second object type has a method only_here

*)


class p1d_1 = 
  object 
    val mutable x = 0
    method move d = x <- x + d
  end

class p1d_2 = 
  object 
    val mutable x = 0
    method move d = x <- x + d
    method only_here x = x + x
  end

let main x = 
  x#move 3


let q = new p1d_1
let p = new p1d_2

let _ = main q
let _ = main p


let mover l = List.iter (fun x -> x#move 10) l

(* let _ = mover [p;q] *)


(*
class p1d_1 : object val mutable x : int method move : int -> unit end
class p1d_2 :
  object
    val mutable x : int
    method move : int -> unit
    method only_here : int -> int
  end
val main : < move : int -> 'a; .. > -> 'a = <fun>
val q : p1d_1 = <obj>
val p : p1d_2 = <obj>
val mover : < move : int -> unit; .. > list -> unit = <fun>

*)



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why can't I use val mover : < move : int -> unit; .. > list -> unit ?
  2001-01-10 12:39 Why can't I use val mover : < move : int -> unit; .. > list -> unit ? Mattias Waldau
@ 2001-01-10 19:16 ` Brian Rogoff
  2001-01-11  9:07   ` Mattias Waldau
  2001-01-10 19:58 ` Alain Frisch
  2001-01-11  9:29 ` Sylvain BOULM'E
  2 siblings, 1 reply; 7+ messages in thread
From: Brian Rogoff @ 2001-01-10 19:16 UTC (permalink / raw)
  To: Mattias Waldau; +Cc: Caml-List

On Wed, 10 Jan 2001, Mattias Waldau wrote:

> In the example below I have two separate classes with no common 
> super class. Both classes have a method 'move'.
> 
> I have no problem using the function main below that can an 
> arbitrary 'objects with move defined'. However, when I try to 
> expand the example to list of objects with move defined, I 
> cannot use this function.

The problem is sticking the objects into the list, not the function
"mover". Ocaml row polymorphism is a bit different than the OO you're 
probably used to; you need to coerce the objects to the common supertype 
before you put them in the list, so that they'll have the same type. Try
something like this 

type t = < move : int -> unit >
let _ = mover [(p :> t) ; (q :> t)] (* Don't forget the parens! *)

You can write collection building functions which do this coercion for 
you. Hope this helps...

-- Brian

> 
> How can I use the function 'mover'? How do I coerce to 
> objects with move defined? 
> 
> /mattias
> 
> 
> 
> 
> (*
> 
> let _ = mover [p;q]
> 
> This expression has type p1d_1 = < move : int -> unit >
> but is here used with type
>   p1d_2 = < move : int -> unit; only_here : int -> int >
> Only the second object type has a method only_here
> 
> *)
> 
> 
> class p1d_1 = 
>   object 
>     val mutable x = 0
>     method move d = x <- x + d
>   end
> 
> class p1d_2 = 
>   object 
>     val mutable x = 0
>     method move d = x <- x + d
>     method only_here x = x + x
>   end
> 
> let main x = 
>   x#move 3
> 
> 
> let q = new p1d_1
> let p = new p1d_2
> 
> let _ = main q
> let _ = main p
> 
> 
> let mover l = List.iter (fun x -> x#move 10) l
> 
> (* let _ = mover [p;q] *)
> 
> 
> (*
> class p1d_1 : object val mutable x : int method move : int -> unit end
> class p1d_2 :
>   object
>     val mutable x : int
>     method move : int -> unit
>     method only_here : int -> int
>   end
> val main : < move : int -> 'a; .. > -> 'a = <fun>
> val q : p1d_1 = <obj>
> val p : p1d_2 = <obj>
> val mover : < move : int -> unit; .. > list -> unit = <fun>
> 
> *)
> 
> 



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why can't I use val mover : < move : int -> unit; .. > list -> unit ?
  2001-01-10 12:39 Why can't I use val mover : < move : int -> unit; .. > list -> unit ? Mattias Waldau
  2001-01-10 19:16 ` Brian Rogoff
@ 2001-01-10 19:58 ` Alain Frisch
  2001-01-11  9:29 ` Sylvain BOULM'E
  2 siblings, 0 replies; 7+ messages in thread
From: Alain Frisch @ 2001-01-10 19:58 UTC (permalink / raw)
  To: Mattias Waldau; +Cc: Caml-List

On Wed, 10 Jan 2001, Mattias Waldau wrote:

> In the example below I have two separate classes with no common 
> super class. Both classes have a method 'move'.
> 
> I have no problem using the function main below that can an 
> arbitrary 'objects with move defined'. However, when I try to 
> expand the example to list of objects with move defined, I 
> cannot use this function.
> 
> How can I use the function 'mover'? How do I coerce to 
> objects with move defined? 

The problem is that you can't put objects of different types in the same
list, and there is no implicit coercion to a subtype in OCaml. As
explained in the manual (section 3.10), you have to use an explicit
subtyping, for instance:

mover [(p :> p1d_1); q]

or:
type m = < move : int -> unit >
mover [(p :> m); (q :> m)]


-- 
  Alain Frisch



^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: Why can't I use val mover : < move : int -> unit; .. > list -> unit ?
  2001-01-10 19:16 ` Brian Rogoff
@ 2001-01-11  9:07   ` Mattias Waldau
  2001-01-11 12:26     ` Michel Schinz
  2001-01-11 13:09     ` Sylvain BOULM'E
  0 siblings, 2 replies; 7+ messages in thread
From: Mattias Waldau @ 2001-01-11  9:07 UTC (permalink / raw)
  To: Brian Rogoff, Mattias Waldau; +Cc: Caml-List

I understand the principle that the compiler must be sure that everywhere I
use the list, the elements will be of the right type. In this case each
element must have the method move.

However, it seems to me that in this case the compiler has already done the
complex part, i.e. realizing that if all objects have a move-method, then
everything is ok. So I don't see the point that I have to coerce explicitily
when putting elements into the list.

In general I don't see the difference to when I call the function main. Why
isn't a coerce necessary here?

let main x =
   x#move 3

let p = new p1d_2

type m = < move : int -> unit >
let _ = main ( q :> m )    (* <== WHY ISN'T THIS NEEDED? *)



Also, I would be interested in how Ocaml can make the call within main and
mover to move efficiently. Other static compiled OO-languages use vtables,
but I don't see how Ocaml can use a vtable. How expensive are these methods
calls? There are no numbers of this in the Ocaml-FAQ

/mattias



-----Original Message-----
From: Brian Rogoff [mailto:bpr@best.com]
Sent: Wednesday, January 10, 2001 8:16 PM
To: Mattias Waldau
Cc: Caml-List
Subject: Re: Why can't I use val mover : < move : int -> unit; .. > list
-> unit ?


On Wed, 10 Jan 2001, Mattias Waldau wrote:

> In the example below I have two separate classes with no common
> super class. Both classes have a method 'move'.
>
> I have no problem using the function main below that can an
> arbitrary 'objects with move defined'. However, when I try to
> expand the example to list of objects with move defined, I
> cannot use this function.

The problem is sticking the objects into the list, not the function
"mover". Ocaml row polymorphism is a bit different than the OO you're
probably used to; you need to coerce the objects to the common supertype
before you put them in the list, so that they'll have the same type. Try
something like this

type t = < move : int -> unit >
let _ = mover [(p :> t) ; (q :> t)] (* Don't forget the parens! *)

You can write collection building functions which do this coercion for
you. Hope this helps...

-- Brian

>
> How can I use the function 'mover'? How do I coerce to
> objects with move defined?
>
> /mattias
>
>
>
>
> (*
>
> let _ = mover [p;q]
>
> This expression has type p1d_1 = < move : int -> unit >
> but is here used with type
>   p1d_2 = < move : int -> unit; only_here : int -> int >
> Only the second object type has a method only_here
>
> *)
>
>
> class p1d_1 =
>   object
>     val mutable x = 0
>     method move d = x <- x + d
>   end
>
> class p1d_2 =
>   object
>     val mutable x = 0
>     method move d = x <- x + d
>     method only_here x = x + x
>   end
>
> let main x =
>   x#move 3
>
>
> let q = new p1d_1
> let p = new p1d_2
>
> let _ = main q
> let _ = main p
>
>
> let mover l = List.iter (fun x -> x#move 10) l
>
> (* let _ = mover [p;q] *)
>
>
> (*
> class p1d_1 : object val mutable x : int method move : int -> unit end
> class p1d_2 :
>   object
>     val mutable x : int
>     method move : int -> unit
>     method only_here : int -> int
>   end
> val main : < move : int -> 'a; .. > -> 'a = <fun>
> val q : p1d_1 = <obj>
> val p : p1d_2 = <obj>
> val mover : < move : int -> unit; .. > list -> unit = <fun>
>
> *)
>
>



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why can't I use val mover : < move : int -> unit; .. > list ->  unit ?
  2001-01-10 12:39 Why can't I use val mover : < move : int -> unit; .. > list -> unit ? Mattias Waldau
  2001-01-10 19:16 ` Brian Rogoff
  2001-01-10 19:58 ` Alain Frisch
@ 2001-01-11  9:29 ` Sylvain BOULM'E
  2 siblings, 0 replies; 7+ messages in thread
From: Sylvain BOULM'E @ 2001-01-11  9:29 UTC (permalink / raw)
  To: Mattias Waldau; +Cc: caml-list

Hi,

Lists are polymorphic but they are uniform : elements of a list must have all 
the same type (which can be any type).

Hence, "mover" is a function that expects a list of objects, all of the same 
type, and which type contains a method "move".

Thus, with 
 q: p1d_1
 p: p1d_2

Expression "[q;q]" is of type "p1d_1 list" and "[p;p]" is of type "p1d_2 list",
thus "mover [q;q]" and "mover [p;p]" are well-typed.

But "[p;q]" is not well-typed.

Here, p1d_2 is subtype of p1d_1 : you can coerce p to have the type p1d_1.
Thus "[(p:>p1d_1);q]" is of type p1d_1 list.
And "mover [(p:>p1d_1);q]" is well-typed.

Sylvain.




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why can't I use val mover : < move : int -> unit; .. > list -> unit ?
  2001-01-11  9:07   ` Mattias Waldau
@ 2001-01-11 12:26     ` Michel Schinz
  2001-01-11 13:09     ` Sylvain BOULM'E
  1 sibling, 0 replies; 7+ messages in thread
From: Michel Schinz @ 2001-01-11 12:26 UTC (permalink / raw)
  To: caml-list

"Mattias Waldau" <mattias.waldau@tacton.se> writes:

[...]

> Also, I would be interested in how Ocaml can make the call within
> main and mover to move efficiently. Other static compiled
> OO-languages use vtables, but I don't see how Ocaml can use a
> vtable. How expensive are these methods calls? There are no numbers
> of this in the Ocaml-FAQ

Jérôme Vouillon wrote a message in this list once to explain the
dispatching technique used in OCaml. The message is archived there:

  http://pauillac.inria.fr/~doligez/caml-guts/objects.txt

Michel.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why can't I use val mover : < move : int -> unit; .. > list ->  unit ?
  2001-01-11  9:07   ` Mattias Waldau
  2001-01-11 12:26     ` Michel Schinz
@ 2001-01-11 13:09     ` Sylvain BOULM'E
  1 sibling, 0 replies; 7+ messages in thread
From: Sylvain BOULM'E @ 2001-01-11 13:09 UTC (permalink / raw)
  To: Mattias Waldau; +Cc: caml-list

> I understand the principle that the compiler must be sure that everywhere I
> use the list, the elements will be of the right type. In this case each
> element must have the method move.
> 
> However, it seems to me that in this case the compiler has already done the
> complex part, i.e. realizing that if all objects have a move-method, then
> everything is ok. So I don't see the point that I have to coerce explicitily
> when putting elements into the list.
> 
Such a coercion is not always possible: forget the "unnecessary" methods has not always a meaning. For instance, let's have an example a bit more complex than yours :

In the context :

class pt = 
  object (_:'a) 
    method compare (x:'a) = true
  end

class qt (i:int) = 
  object (s:'a)
    val mutable state = i
    method compare (x:'a) = x#get = s#get 
    method get = state 
  end

let p = new pt and q1 = new qt 1 and q2 = new qt 2;;

(** test if x is comparable to all elements of l **)
(* val compare_iter : < compare : 'a -> bool; .. > list -> 'a -> bool *)
let compare_iter l x = List.fold_left (fun b y -> b && y#compare x) true l;; 

compare_iter [p;p] p;;
compare_iter [q1;q2] q1;;

Both these expressions below are not well-typed :
compare_iter [q1;q2] p;;
compare_iter [(q1:> pt);(q2:> pt)] p;;

Indeed, an object of type "qt" can not be coerced to an object of type "pt" because an object of type "qt" needs an object with a "get" method as argument for "compare". What is interesting here with ocaml polymorphism, is that you can however have a function as "compare_iter" which can both handle "lists of pt" and "lists of qt".


Hope this helps,

Sylvain.



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2001-01-11 17:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-01-10 12:39 Why can't I use val mover : < move : int -> unit; .. > list -> unit ? Mattias Waldau
2001-01-10 19:16 ` Brian Rogoff
2001-01-11  9:07   ` Mattias Waldau
2001-01-11 12:26     ` Michel Schinz
2001-01-11 13:09     ` Sylvain BOULM'E
2001-01-10 19:58 ` Alain Frisch
2001-01-11  9:29 ` Sylvain BOULM'E

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).