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 mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 9A3E57EEB4 for ; Sun, 3 Feb 2013 02:53:44 +0100 (CET) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of cedilla@gmail.com) identity=pra; client-ip=209.85.223.179; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="cedilla@gmail.com"; x-sender="cedilla@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of cedilla@gmail.com designates 209.85.223.179 as permitted sender) identity=mailfrom; client-ip=209.85.223.179; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="cedilla@gmail.com"; x-sender="cedilla@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-ie0-f179.google.com) identity=helo; client-ip=209.85.223.179; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="cedilla@gmail.com"; x-sender="postmaster@mail-ie0-f179.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AsEBAFHCDVHRVd+zm2dsb2JhbABFhki4YggWDgEBAQEBCAkLCRQngh8BAQQBIwQZARsdAQMBCwYDAgsNKgICIQEBEQEFARwGE4d+AQMJBpQ1jxyLZU+Ce4NwChknDVmIdwEFDIwRhCKBEwOIZothgViLP4MxFimEPw X-IPAS-Result: AsEBAFHCDVHRVd+zm2dsb2JhbABFhki4YggWDgEBAQEBCAkLCRQngh8BAQQBIwQZARsdAQMBCwYDAgsNKgICIQEBEQEFARwGE4d+AQMJBpQ1jxyLZU+Ce4NwChknDVmIdwEFDIwRhCKBEwOIZothgViLP4MxFimEPw X-IronPort-AV: E=Sophos;i="4.84,591,1355094000"; d="scan'208";a="876141" Received: from mail-ie0-f179.google.com ([209.85.223.179]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 03 Feb 2013 02:50:16 +0100 Received: by mail-ie0-f179.google.com with SMTP id k11so3346716iea.38 for ; Sat, 02 Feb 2013 17:53:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type; bh=N6S8dWISus+tCZ/cD85572aEHY+IvrFLg2RvMxwF/Nk=; b=f7jrKw3RgXvVF8QRAxflS+OtANrHZfdxWcb2U6fvSiEtCMGk/vuJ5Zu9imICoHOFUP E7CCGQISo8kQF7h+Ybx3sj8RVNyz4lnmugWk0ivP57tMJGhw+E1jGeUZaZ+Lkse+Fpjk UbYswbaMg3fHWbtBn+ZRVdDtfArJXkRlAkt9/zP99gh9C0RZew7Vcbl7o1Yb9sg/MsUz cgz7BV/dT+Js3nCu0OcYxqzK8bpqJ8zVDMSoZRBZdaZgSqDcWwa98grs5Q8VDhv+Jw4U XRkmE21yPUf0YlH6wvawyY4H9Y9qjLLmTomGP+7e2iqld6u8AKvVa3imaduXgEk7pItu eINA== MIME-Version: 1.0 X-Received: by 10.50.180.196 with SMTP id dq4mr1776569igc.71.1359856422009; Sat, 02 Feb 2013 17:53:42 -0800 (PST) Received: by 10.64.6.1 with HTTP; Sat, 2 Feb 2013 17:53:41 -0800 (PST) In-Reply-To: References: Date: Sat, 2 Feb 2013 17:53:41 -0800 Message-ID: From: Reed Wilson To: Jeremy Yallop Cc: caml-list@inria.fr Content-Type: multipart/alternative; boundary=14dae93407a3fabc5a04d4c83e7a X-Validation-by: cedilla@gmail.com Subject: Re: [Caml-list] Objects and polymorphic variants --14dae93407a3fabc5a04d4c83e7a Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Perfect! That's exactly what I need. If I use your idea and provide explicit typing for the other two methods everything works fine. My final (working) methods: method private method_12 : 'a. int -> ([> `One | `Two ] as 'a) =3D function | 1 -> `One | _ -> `Two method method_123 : int -> [ `One | `Two | `Three ] =3D function | 3 -> `Three | x -> o#method_12 x method method_124 : int -> [ `One | `Two | `Four ] =3D function | 4 -> `Four | x -> o#method_12 x OCaml gives me the desired types: method private method_12 : 'a. int -> ([> `One | `Two ] as 'a) method method_123 : int -> [ `One | `Three | `Two ] method method_124 : int -> [ `Four | `One | `Two ] Thanks for the quick response, Reed On Sat, Feb 2, 2013 at 4:13 PM, Jeremy Yallop wrote: > On 2 February 2013 23:18, Reed Wilson wrote: > > What I really want is a signature like this: > > method private method_12 : int -> [ > `One | `Two ] > > method method_123 : int -> [ `One | `Two | `Three ] > > method method_124 : int -> [ `One | `Two | `Four ] > > > > If I replace method_12 with a function outside the class it works fine, > but > > for whatever reason method_12 really wants to be the exact same type as > > method_123 and method_124. > > > > Is there any way around this typing requirement for methods? > > I think that the problem arises because methods are typed similarly to > mutually-recursive functions. Unless you give type signatures, both > functions that are marked as mutually recursive and methods are > assumed to be monomorhpic. For example, in > > let rec f =3D fun x -> x > and g =3D fun x -> f (x + 1) > > the types are > > val f : int -> int > val g : int -> int > > i.e. f is assigned the type with which it is used in the body of g. > If you remove the (unnecessary) mutual recursion then the more general > types will be inferred; for example, in > > let f =3D fun x -> x > let g =3D fun x -> f (x + 1) > > the types are > > val f : 'a -> 'a > val g : int -> int > > It's also possible to ensure that f is assigned the more general type > by using a type signature: > > let rec f : 'a. 'a -> 'a =3D fun x -> x > and g =3D fun x -> f (x + 1) > > With objects, the situation is similar, except that you can't mark > methods non-recursive, so you have to give a type signature to avoid > the monomorphising. So > > object (self) > method f =3D fun x -> x > method g =3D fun x -> self#f (x + 1) > end > > receives the type > > < f : int -> int; > g : int -> int > > > whereas > > object (self) > method f : 'a. 'a -> 'a =3D fun x -> x > method g =3D fun x -> self#f (x + 1) > end > > receives the more general type > > < f : 'a. 'a -> 'a; > g : int -> int > > > In your example you can ensure that the type you want is inferred by > annotating method_12 with a polymorphic signature: > > object (self) > method private method_12 : 'a. int -> ([> `One | `Two] as 'a) =3D > function > | 1 -> `One > | _ -> `Two > > method method_123 =3D function > | 3 -> `Three > | x -> self#method_12 x > > method method_124 =3D function > | 4 -> `Four > | x -> self#method_12 x > end > > Now the inferred types for method_123 and method_125 are distinct: > > < method_123 : int -> [> `One | `Three | `Two ]; > method_124 : int -> [> `Four | `One | `Two ] > > > Hope that helps a bit, > > Jeremy. > --=20 =C3=A7 --14dae93407a3fabc5a04d4c83e7a Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Perfect! That's exactly what I need. If I use your ide= a and provide explicit typing for the other two methods everything works fi= ne.

My final (working) methods:
method private method_12 : 'a. int -> ([> `= One | `Two ] as 'a) =3D function
=C2=A0 | 1 -> `One
= =C2=A0 | _ -> `Two

method method_123 : int -> [ `One | `Two | `Three ] = =3D function
=C2=A0 | 3 -&= gt; `Three
=C2=A0 | x ->= ; o#method_12 x

method method_124 : int -> [ `One | `Two | `Four ] = =3D function
=C2=A0 | 4 -&= gt; `Four
=C2=A0 | x ->= o#method_12 x

OCaml gives me the desired types:
method private method_12 : 'a. int -> ([> `One | `Two ] as = 'a)
method method_123 : int -> [ `One | `Three | `Two ]
method method_124 : int -> [ `Four | `One | `Two ]

Thanks for the quick response,
Reed


On Sat, Feb 2, 2013 at 4:13 PM, Jeremy Yallop <yallop@gmail.com> wrote:
On 2 February 2013 23:18, Reed Wilson <cedilla@gmail.com> wrote:
> What I really want is a signature like this:
> method private method_12 : int -> [ > `One | `Two ]
> method method_123 : int -> [ `One | `Two | `Three ]
> method method_124 : int -> [ `One | `Two | `Four ]
>
> If I replace method_12 with a function outside the class it works fine= , but
> for whatever reason method_12 really wants to be the exact same type a= s
> method_123 and method_124.
>
> Is there any way around this typing requirement for methods?

I think that the problem arises because methods are typed similarly t= o
mutually-recursive functions. =C2=A0Unless you give type signatures, both functions that are marked as mutually recursive and methods are
assumed to be monomorhpic. =C2=A0For example, in

=C2=A0 =C2=A0 let rec f =3D fun x -> x
=C2=A0 =C2=A0 =C2=A0 =C2=A0 and g =3D fun x -> f (x + 1)

the types are

=C2=A0 =C2=A0 val f : int -> int
=C2=A0 =C2=A0 val g : int -> int

i.e. f is assigned the type with which it is used in the body of g.
If you remove the (unnecessary) mutual recursion then the more general
types will be inferred; for example, in

=C2=A0 =C2=A0 let f =3D fun x -> x
=C2=A0 =C2=A0 let g =3D fun x -> f (x + 1)

the types are

=C2=A0 =C2=A0 val f : 'a -> 'a
=C2=A0 =C2=A0 val g : int -> int

It's also possible to ensure that f is assigned the more general type by using a type signature:

=C2=A0 =C2=A0 let rec f : 'a. 'a -> 'a =3D fun x -> x
=C2=A0 =C2=A0 =C2=A0 =C2=A0 and g =3D fun x -> f (x + 1)

With objects, the situation is similar, except that you can't mark
methods non-recursive, so you have to give a type signature to avoid
the monomorphising. =C2=A0So

=C2=A0 =C2=A0object (self)
=C2=A0 =C2=A0 =C2=A0method f =3D fun x -> x
=C2=A0 =C2=A0 =C2=A0method g =3D fun x -> self#f (x + 1)
=C2=A0 =C2=A0end

receives the type

=C2=A0 =C2=A0< f : int -> int;
=C2=A0 =C2=A0 =C2=A0g : int -> int >

whereas

=C2=A0 =C2=A0object (self)
=C2=A0 =C2=A0 =C2=A0method f : 'a. 'a -> 'a =3D fun x -> = x
=C2=A0 =C2=A0 =C2=A0method g =3D fun x -> self#f (x + 1)
=C2=A0 =C2=A0end

receives the more general type

=C2=A0 =C2=A0< f : 'a. 'a -> 'a;
=C2=A0 =C2=A0 =C2=A0g : int -> int >

In your example you can ensure that the type you want is inferred by
annotating method_12 with a polymorphic signature:

=C2=A0 =C2=A0object (self)
=C2=A0 =C2=A0 =C2=A0method private method_12 : 'a. int -> ([> `On= e | `Two] as 'a) =3D function
=C2=A0 =C2=A0 =C2=A0 =C2=A0| 1 -> `One
=C2=A0 =C2=A0 =C2=A0 =C2=A0| _ -> `Two

=C2=A0 =C2=A0 =C2=A0method method_123 =3D function
=C2=A0 =C2=A0 =C2=A0 | 3 -> `Three
=C2=A0 =C2=A0 =C2=A0 | x -> self#method_12 x

=C2=A0 =C2=A0 =C2=A0method method_124 =3D function
=C2=A0 =C2=A0 =C2=A0 | 4 -> `Four
=C2=A0 =C2=A0 =C2=A0 | x -> self#method_12 x
=C2=A0 =C2=A0end

Now the inferred types for method_123 and method_125 are distinct:

=C2=A0 < method_123 : int -> [> `One | `Three | `Two ];
=C2=A0 =C2=A0 method_124 : int -> [> `Four | `One | `Two ] >

Hope that helps a bit,

Jeremy.



--
=C3=A7
--14dae93407a3fabc5a04d4c83e7a--