Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] Coercion of arrays of objects (and some other containers)

0 views
Skip to first unread message

Martin Jambon

unread,
Apr 12, 2005, 8:24:40 PM4/12/05
to caml...@inria.fr
Here is my problem:

# let obj =
object
method a = ()
method b = ()
end;;
val obj : < a : unit; b : unit > = <obj>

(* That is nice: *)
# ([ obj ] :> < a : unit > list);;
- : < a : unit > list = [<obj>]

(* But why doesn't it work with arrays? *)
# ([| obj |] :> < a : unit > array);;
Characters 1-10:
([| obj |] :> < a : unit > array);;
^^^^^^^^^
This expression cannot be coerced to type < a : unit > array; it has type
< a : unit; b : unit > array
but is here used with type < a : unit > array
Only the first object type has a method b


In practice I have this problem with a hash table of objects, and I
expected it to work since it works fine with lists of the same
type of objects...
Is there any workaround?

Martin

--
Martin Jambon, PhD
http://martin.jambon.free.fr


_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Olivier Andrieu

unread,
Apr 12, 2005, 8:53:52 PM4/12/05
to martin...@emailuser.net, caml...@inria.fr
Salut Martin,

> Martin Jambon [Tue, 12 Apr 2005]:


> Here is my problem:
>
> # let obj =
> object
> method a = ()
> method b = ()
> end;;
> val obj : < a : unit; b : unit > = <obj>
>
> (* That is nice: *)
> # ([ obj ] :> < a : unit > list);;
> - : < a : unit > list = [<obj>]
>
> (* But why doesn't it work with arrays? *)
> # ([| obj |] :> < a : unit > array);;
> Characters 1-10:
> ([| obj |] :> < a : unit > array);;
> ^^^^^^^^^
> This expression cannot be coerced to type < a : unit > array; it has type
> < a : unit; b : unit > array
> but is here used with type < a : unit > array
> Only the first object type has a method b

It's a variance problem : a list is covariant so the coercion
works. But an array is invariant (because of the Array.set
operations).

Otherwise after coercion you would be able to do store in the array an
object without a `b' method, this object being also reachable through
the original array.

> In practice I have this problem with a hash table of objects, and I
> expected it to work since it works fine with lists of the same
> type of objects...
> Is there any workaround?

Maybe this :

Array.map (fun o -> (o :> < a : unit >)) [| obj |]

--
Olivier

Jacques Garrigue

unread,
Apr 12, 2005, 9:04:07 PM4/12/05
to martin...@emailuser.net, caml...@inria.fr
From: Martin Jambon <martin...@emailuser.net>

> Here is my problem:
>
> # let obj =
> object
> method a = ()
> method b = ()
> end;;
> val obj : < a : unit; b : unit > = <obj>
>
> (* That is nice: *)
> # ([ obj ] :> < a : unit > list);;
> - : < a : unit > list = [<obj>]
>
> (* But why doesn't it work with arrays? *)
> # ([| obj |] :> < a : unit > array);;
> Characters 1-10:
> ([| obj |] :> < a : unit > array);;
> ^^^^^^^^^
> This expression cannot be coerced to type < a : unit > array; it has type
> < a : unit; b : unit > array
> but is here used with type < a : unit > array
> Only the first object type has a method b

Suppose that it worked.
Then you could have this scenario.
let arr = [|obj|];;
let arr' = (arr :> <a:unit> array);;
arr'.(0) <- object method a = () end;;
arr.(0)#b;;
Segmentation fault.

Such subtyping is allowed in Java, but this is an unsafe part of the
type system, which requires time-consuming runtime checks.

> In practice I have this problem with a hash table of objects, and I
> expected it to work since it works fine with lists of the same
> type of objects...
> Is there any workaround?

If you don't need to add objects to this hash table, this is possible
with the following approach:

class ['a,+'b] table tbl =
object
val tbl : ('a,'b) Hashtbl.t = tbl
method find = Hashtbl.find tbl
method find_all = Hashtbl.find_all tbl
method mem = Hashtbl.mem tbl
end
(* class ['a, 'b] table :
('a, 'b) Hashtbl.t ->
object
val tbl : ('a, 'b) Hashtbl.t
method find : 'a -> 'b
method find_all : 'a -> 'b list
method mem : 'a -> bool
end *)
let coerce tbl = (tbl : ('a,<a:int;b:int>) table :> ('a,<a:int>) table)

See that 'b appears only in covariant positions, allowing its
subtyping.

Jacques Garrigue

Matthieu Dubuget

unread,
Apr 13, 2005, 2:46:18 AM4/13/05
to caml...@inria.fr
I'm sorry, but I feel stupid.

The variance and covariance terms/notions appear often in this list, and
seems to be very basic notions.

I tried to find explanation on internet but did not succeed.

Could somebody point me some links to understand, please?

Thanks in advance

Salutations

Matthieu

Olivier Andrieu

unread,
Apr 13, 2005, 10:18:20 AM4/13/05
to matthieu...@laposte.net, caml...@inria.fr
Matthieu Dubuget [Wed, 13 Apr 2005]:

> I'm sorry, but I feel stupid.
>
> The variance and covariance terms/notions appear often in this
> list, and seems to be very basic notions.
>
> I tried to find explanation on internet but did not succeed.
>
> Could somebody point me some links to understand, please?

I do not have a link but the idea (as I understand it) is simple :

This concerns parameterized types ('a t) and how a subtyping relation
on the parameter can yield a subtyping relation on the type.

When the parameter is covariant :
if a is a subtype of b then a t is a subtype of b t

When the parameter is contravariant :
if a is a subtype of b then b t is a subtype of a t

For instance lists are covariant. [`A|`B|`C] is a supertype of [`A|`B]
so a [`A|`B|`C] list is a supertype of [`A|`B] list.

Function arguments are contravariant : ([`A|`B] -> unit) is a
supertype of ([`A|`B|`C] -> unit). When you have a function that
accepts A B or C, you can also view it as a function that accepts just
A or B (qui peut le plus peut le moins).

Records with mutable fields (or arrays) are neither covariant nor
contravariant.

Well maybe my terminology isn't quite correct but I hope you get the
idea.

--
Olivier

0 new messages