* 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