From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by sympa.inria.fr (Postfix) with ESMTPS id 8A5FB7EC41 for ; Wed, 24 Oct 2012 22:36:14 +0200 (CEST) Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of didier.cassirame@gmail.com) identity=pra; client-ip=209.85.219.54; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="didier.cassirame@gmail.com"; x-sender="didier.cassirame@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail4-smtp-sop.national.inria.fr: domain of didier.cassirame@gmail.com designates 209.85.219.54 as permitted sender) identity=mailfrom; client-ip=209.85.219.54; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="didier.cassirame@gmail.com"; x-sender="didier.cassirame@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-oa0-f54.google.com) identity=helo; client-ip=209.85.219.54; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="didier.cassirame@gmail.com"; x-sender="postmaster@mail-oa0-f54.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AiACAM5QiFDRVds2m2dsb2JhbABEhhSpXYkmAYhdCCMBAQEBAQgJCwkUJ4IeAQEBAwESAg8EGQEbEgsBAwELBgMCCwMKDR0CAiEBAREBBQEKEgYTCAoJB4dPAQMJBgudP2AJA4tZT4J2hH0KGScDClmIdQEFDIpuZ4VagRMDlB6BVYEXihKDLxYphBM X-IronPort-AV: E=Sophos;i="4.80,642,1344204000"; d="scan'208";a="160290544" Received: from mail-oa0-f54.google.com ([209.85.219.54]) by mail4-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 24 Oct 2012 22:36:13 +0200 Received: by mail-oa0-f54.google.com with SMTP id n9so1601455oag.27 for ; Wed, 24 Oct 2012 13:36:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=1fov3K7shWVnknIpuwBzivRKw3+mocHbbtqfQbp3iXo=; b=zQxv7lhSWF1di5OfqNYidKUGFuvYkUFrVxdgZ7TCVKp+I9HniPlqn+MCIfA/zvouPq xQ4jDevnRJAh78ELjluznTRWbcHiKs6yiibyFoBFYDKabIlfAHiKxizI/kjtuO4srRB6 wsKaW0hWmqT5gbXptssvn1M3ytQE6voqkH1dT1rdwMcDdwceR31zGcm0rKbK0N1NITD9 tu0RIyDyGIQ1kwI1BrT3VbQ5mjcb19pcyzMeIZjr/IMeE8c/S7w1AlRkYj8d7ALrCvMP IvNEuKrO6TEFc63GrfxcUVFZ11CHTfKmSxBEFAxF5RXccycosO6Lo8IMUhTySgv4uRAh 4lAw== Received: by 10.60.169.234 with SMTP id ah10mr15244725oec.12.1351110971777; Wed, 24 Oct 2012 13:36:11 -0700 (PDT) MIME-Version: 1.0 Received: by 10.60.137.198 with HTTP; Wed, 24 Oct 2012 13:35:51 -0700 (PDT) In-Reply-To: <20121024213213.2e447165b7c4ea9ad9d8e154@gmerlin.de> References: <20121024200310.9c639f43a97263423e113500@gmerlin.de> <20121024213213.2e447165b7c4ea9ad9d8e154@gmerlin.de> From: Didier Cassirame Date: Wed, 24 Oct 2012 22:35:51 +0200 Message-ID: To: Christopher Zimmermann Cc: caml-list@inria.fr Content-Type: multipart/alternative; boundary=bcaec54d4d8e86623b04ccd409b6 Subject: Re: [Caml-list] Re: typing mutually recursive classes --bcaec54d4d8e86623b04ccd409b6 Content-Type: text/plain; charset=UTF-8 Hi, Your first two examples compile without problem on my system, using either v. 3.11.2 or 4.00. If you use a parameterized registry class on the element type, you will not be able to store polymorphic values, which is, I reckon, what you probably want to achieve. I don't think there's a way to avoid casting the parameters of set to the #element superclass outside the set method. If you only have one final element class, just use the parameterized version of the registry, or replace the register method by a private register_elem method, and add a public register method in the subclass, doing the cast. Something like that : module P = struct class element id (registry :registry) = object method registry = registry end and registry = object val mutable set : element list = [] method register_elem : element -> unit = fun s -> set <- s :: set end end module I = struct class element id registry = let r = (registry :> P.registry) in object(self) inherit P.element id r as super end class registry = object(self) inherit P.registry as super method register : element -> unit = fun x -> super#register_elem (x :> P.element) end end Cheers, Didier 2012/10/24 Christopher Zimmermann > On Wed, 24 Oct 2012 20:40:27 +0200 > Gabriel Scherer wrote: > > > I don't really understand what you are trying to achieve with this > > #foo types. > > It's the simplest statement possible to demonstrate the typing error I > ran into. Even simpler: > > class type a = object end > and b = > object > method foo: 'a. (#a as 'a) -> unit > end > > fails, but > > class type a = object end > class type b = > object > method foo: 'a. (#a as 'a) -> unit > end > > > works fine. Why? > > > What would even be the type of "set" in your example? You > > cannot hold a mutable reference to a polymorphic type (#element list), > > so I'm not sure what you would have but (element list). > That's correct. It should read > val mutable set = [] > method register :'a. (#element as 'a) -> unit = > fun s -> > set <- (s : #element :> element) :: set > > > If you're > > going to coerce your elements into the common (element) supertype > > anyway, why insist on having flexible bounds? You could just use > > (registry) and (element), coerce when needed (foo :> element), and get > > rid of those pesky typing issues. > > That's my current workaround for this issue. But I would prefer a > solution where the coercion happens in the registry. > > > > > On Wed, Oct 24, 2012 at 8:03 PM, Christopher Zimmermann > > wrote: > > > Hi, > > > > > > I have a problem with typing a system of mutually recursive classes. > > > > > > This piece of code fails to compile: > > > > > > class a = > > > object end > > > and b = > > > object > > > method foo: a -> int = > > > fun s -> 3 > > > end;; > > > > > > Error: The universal type variable 'a cannot be generalized: > > > it escapes its scope. > > > > > > > > > But this compiles fine: > > > > > > class a = > > > object end > > > class b = > > > object > > > method foo: 'a. (#a as 'a) -> int = > > > fun s -> 3 > > > end;; > > > > > > > > > What I actually want to do is this: > > > > > > class element id (registry :#registry) = > > > object > > > method registry = registry > > > end > > > > > > and registry = > > > object > > > val set = [] > > > method register :'a. (#element as 'a) -> unit = > > > fun s -> > > > set <- s :: set > > > end > > > > > > > > > Any ideas how to do this without parametrizing the classes? > > > > > > Christopher > > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > --bcaec54d4d8e86623b04ccd409b6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi,

Your first two examples compile without proble= m on my system, using either v. 3.11.2 or 4.00.
If you use a parameteri= zed registry class on the element type, you will not be able to store polym= orphic values, which is, I reckon, what you probably=C2=A0want to achieve.= =C2=A0
I don't think there's a way to avoid casting the parameters of= set to the #element superclass outside the set method. If you only have on= e final element class, just use the parameterized version of the registry, = or replace the register method by a private register_elem method, and add a= public register method in the subclass, doing the cast.

Something like that :

mod= ule P =3D
struct

=C2=A0 class element id= (registry :registry) =3D
=C2=A0 object
=C2=A0 =C2=A0 m= ethod registry =3D registry
=C2=A0 end

=C2=A0 and registry =3D
= =C2=A0 object
=C2=A0 =C2=A0 val mutable set : element list =3D []=
=C2=A0 =C2=A0 method register_elem : element -> unit =3D
=C2=A0 =C2=A0 =C2=A0 fun s ->
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 set <- s :: set
=C2=A0 end

end

modul= e I =3D
struct

=C2=A0 class element id r= egistry =3D
=C2=A0 =C2=A0 let r =3D (registry :> P.registry) i= n
=C2=A0 object(self)

=C2=A0 =C2=A0 inherit P.element id r as super

=C2=A0 end

=C2=A0 class registry = =3D
=C2=A0 object(self)

=C2=A0 =C2=A0 in= herit P.registry as super

=C2=A0 =C2=A0 method register : element -> unit =3D
=
=C2=A0 =C2=A0 =C2=A0 fun x -> super#register_elem (x :> P.elemen= t)

=C2=A0 end

end

Cheers,

Didier

2012/10/24 Christopher Zimmermann <madroach@gmerlin.de><= /span>
On Wed, 24 Oct 2012 20:40:= 27 +0200
Gabriel Scherer <gabriel.sc= herer@gmail.com> wrote:

> I don't really understand what you are trying to achieve with this=
> #foo types.

It's the simplest statement possible to demonstrate the typing er= ror I
ran into. Even simpler:

class type a =3D object end
and b =3D
=C2=A0 object
=C2=A0 =C2=A0 method foo: 'a. (#a as 'a) -> unit
=C2=A0 end

=C2=A0 fails, but

class type a =3D object end
class type b =3D
=C2=A0 object
=C2=A0 =C2=A0 method foo: 'a. (#a as 'a) -> unit
=C2=A0 end


works fine. Why?

> What would even be the type of "set" in your example? You
> cannot hold a mutable reference to a polymorphic type (#element list),=
> so I'm not sure what you would have but (element list).
That's correct. It should read
=C2=A0 val mutable set =3D []
=C2=A0 method register :'a. (#element as 'a) ->= ; unit =3D
=C2=A0 =C2=A0 fun s ->
=C2=A0 =C2=A0 =C2=A0 set <- (s : #element :> element) :: set

> If you're
> going to coerce your elements into the common (element) supertype
> anyway, why insist on having flexible bounds? You could just use
> (registry) and (element), coerce when needed (foo :> element), and = get
> rid of those pesky typing issues.

That's my current workaround for this issue. But I would prefer a=
solution where the coercion happens in the registry.

>
> On Wed, Oct 24, 2012 at 8:03 PM, Christopher Zimmermann
> <madroach@gmerlin.de>= wrote:
> > Hi,
> >
> > I have a problem with typing a system of mutually recursive class= es.
> >
> > This piece of code fails to compile:
> >
> > class a =3D
> > =C2=A0 object end
> > and b =3D
> > =C2=A0 object
> > =C2=A0 =C2=A0 method foo: a -> int =3D
> > =C2=A0 =C2=A0 =C2=A0 fun s -> 3
> > =C2=A0 end;;
> >
> > Error: The universal type variable 'a cannot be generalized:<= br> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0it escapes its scope.
> >
> >
> > But this compiles fine:
> >
> > class a =3D
> > =C2=A0 object end
> > class b =3D
> > =C2=A0 object
> > =C2=A0 =C2=A0 method foo: 'a. (#a as 'a) -> int =3D
> > =C2=A0 =C2=A0 =C2=A0 fun s -> 3
> > =C2=A0 end;;
> >
> >
> > What I actually want to do is this:
> >
> > class element id (registry :#registry) =3D
> > =C2=A0 object
> > =C2=A0 =C2=A0 method registry =3D registry
> > =C2=A0 end
> >
> > and registry =3D
> > =C2=A0 object
> > =C2=A0 =C2=A0 val set =3D []
> > =C2=A0 =C2=A0 method register :'a. (#element as 'a) ->= unit =3D
> > =C2=A0 =C2=A0 =C2=A0 fun s ->
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 set <- s :: set
> > =C2=A0 end
> >
> >
> > Any ideas how to do this without parametrizing the classes?
> >
> > Christopher


--
Caml-list mailing list. =C2=A0Subscription management and archives:
ht= tps://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

--bcaec54d4d8e86623b04ccd409b6--