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 6AD497EE48 for ; Sun, 25 Jan 2015 20:57:50 +0100 (CET) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of jordojw@gmail.com) identity=pra; client-ip=209.85.220.47; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="jordojw@gmail.com"; x-sender="jordojw@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of jordojw@gmail.com designates 209.85.220.47 as permitted sender) identity=mailfrom; client-ip=209.85.220.47; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="jordojw@gmail.com"; x-sender="jordojw@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-pa0-f47.google.com) identity=helo; client-ip=209.85.220.47; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="jordojw@gmail.com"; x-sender="postmaster@mail-pa0-f47.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AlUBAFxKxVTRVdwvlGdsb2JhbABahDHGL4V7AoEPQwEBAQEBEQEBAQEHCwsJEjCEDAEBAQMBAQIPFRMGARsdAQMBCwYFCwMKLiMRAQUBHAYTGgiHdQEDCQgFsVE+MY0ZgneJPQoZJw1UhDsBAQEBAQEBAQEBAQEBAQEBAQEBAQERAQUOjzczB4MWgRMFigeCdoJmiCyBFYEEhBtqh2GBczWBFYQxToJCAQEB X-IPAS-Result: AlUBAFxKxVTRVdwvlGdsb2JhbABahDHGL4V7AoEPQwEBAQEBEQEBAQEHCwsJEjCEDAEBAQMBAQIPFRMGARsdAQMBCwYFCwMKLiMRAQUBHAYTGgiHdQEDCQgFsVE+MY0ZgneJPQoZJw1UhDsBAQEBAQEBAQEBAQEBAQEBAQEBAQERAQUOjzczB4MWgRMFigeCdoJmiCyBFYEEhBtqh2GBczWBFYQxToJCAQEB X-IronPort-AV: E=Sophos;i="5.09,464,1418079600"; d="scan'208";a="97638010" Received: from mail-pa0-f47.google.com ([209.85.220.47]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 25 Jan 2015 20:57:49 +0100 Received: by mail-pa0-f47.google.com with SMTP id lj1so7678012pab.6 for ; Sun, 25 Jan 2015 11:57:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=content-type:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=9Fcs9fOY3uGxu6timV4mzXaf6CxTDR6N87jx/WqTiAA=; b=KIj056lpcU7O0saYRXXFZ8pLCW7u3fCZUFLBEj/r8UAABNY+riXGv7w341jr5Qhrgb RaePyN8jFKrYdLNPJH+huZzKlrI6rtSx0c5p34raNUtEJ+/3qk9YBTw7YaqjWp3RvCwN Q8rZUn1ucdJ9LpBHH7D8wXPOMVT6G2iDcE7vv3k3LVnDJd2hihHD3ZK4CuPJivEwc5BC 7QsrtbUHyy7STD5WqdiEhhRvV09B++ryEvHwgoKzsenWor6X0VPFnNWbXNMLnNUL8DzQ VlzG7T+/y87jHHF7xp2s1QCSgp3BMeaFu3BAWuTaLH/WjTE5lfck21jmJPdSUOy/BvK8 c9Kg== X-Received: by 10.70.130.108 with SMTP id od12mr28570769pdb.109.1422215867527; Sun, 25 Jan 2015 11:57:47 -0800 (PST) Received: from [10.9.154.29] ([166.170.39.77]) by mx.google.com with ESMTPSA id rx1sm7873024pbc.86.2015.01.25.11.57.43 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 25 Jan 2015 11:57:45 -0800 (PST) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (1.0) From: Jordo X-Mailer: iPhone Mail (12B440) In-Reply-To: Date: Sun, 25 Jan 2015 11:57:41 -0800 Cc: Mailing List OCaml Content-Transfer-Encoding: quoted-printable Message-Id: <02B4AAD3-9AD1-42F8-BDCA-FFAA7EA43F03@gmail.com> References: To: David Allsopp X-Validation-by: jordojw@gmail.com Subject: Re: [Caml-list] Explicit Arity with Polymorphic Variants You've listed some good examples of why this would be difficult to implemen= t and some examples of how this would be confusing to developers. But I am = having a hard time seeing how you have demonstrated why polymorphic variant= s cannot assume two forms - each incompatible with the other, with any part= icular form being completely inferred. I am not claiming that a distinction= between the two forms is not needed at the type level - the two forms woul= d be incompatible with each other at the type level just as they are incomp= atible for standard variants. My question was why does a distinction at the= type level require a type *definition* (which was your original claim). Fo= r the sake of experimentation, assume you can create any syntax you need th= at would unambiguously express which of the two forms is being reasoned abo= ut in all situations. The fact that this is been attempted before (revised syntax) without much s= uccess or adoption doesn't discourage me from experimenting with it again t= o learn about the internals of variants. Jordan W Sent from my iPhone > On Jan 25, 2015, at 2:11 AM, David Allsopp wrote: >=20 > Jordan W wrote: >> It sounds like this has nothing to do with polymorphic variants >> not requiring a type definition. >=20 > No, it still has everything to do with it! (I'm not sure I agree with Gab= riel's assessment that there was a lack of need for polymorphic variants to= support both variants - I would think it was considered to be a bad idea..= . but I'm sure Jacques can say what he thought!). >=20 >> I agree it's an ugly hack, but one that seems to accomplish something >> of value. There are two distinctions that I know of between single=20 >> argument tuple constructors and mult-argument constructors: >>=20 >> 1. Memory layout is different (Is this still the case)? >=20 > Yes - for the tuple case, the standard variant is a block of size one poi= nting to the tuple, for the flat case it has size n where n is the arity of= the constructor. In both cases the block is tagged with the constructor nu= mber from the type definition. >=20 >> 2. First-classness of arguments is different. With a single argument=20 >> tuple, the contents can be passed around and then finally placed into=20 >> the constructor without any overhead of destructuring/restructuring. >=20 > The destructuring is almost always useful, I think? I can't imagine a cas= e where not being able to match on just the tuple is something you'd want t= o avoid. The reason for having the two layouts for standard variants is bec= ause the memory layout is more efficient in the flat case, so if you don't = need to be able to match on just the tuple then you can get a small benefit= in memory efficiency by declaring that. >=20 > For polymorphic variants, where there's no type definition, it makes sens= e that the tuple version is the layout for the same reason - especially as = polymorphic variants are less memory-efficient than standard variants anywa= y. >=20 >> Both of these seem like desirable controls to have and possibly justifies >> the existence of having two modes. Under that assumption, having some wa= y=20 >> to designate in the parse tree which is intended (at the pattern or expr= ession >> level) seems like a good idea - and even if that mechanism is the ugly=20 >> `explicit_arity` hack. So I understand the justification for the current= state >> of the world. >> I'm curious why there is not some way to achieve the same with polymorph= ic=20 >> variants (even if that is also a hack). Are you saying it was simply bec= ause=20 >> time has not permitted it? Looking deeper, it seems polymorphic variants= are=20 >> incapable of accepting multiple arguments and only ever accept a single = tuple=20 >> (which is therefore allowed to be first class). >=20 > You can't have both memory layouts for polymorphic variants without havin= g a type annotation to distinguish between them. Suppose you have what you = want, and [@explicit_arity] is the way to create them: >=20 > Normal tuple case: >=20 > # `Foo (1, 2);; > - : [> `Foo of (int * int) ] =3D `Foo (1, 2) >=20 > Proposed flat case: >=20 > # `Foo(1, 2) [@explicit_arity];; > - : [> `Foo of int * int ] =3D `Foo (1, 2) >=20 > So that introduces another level of obscure complexity to polymorphic var= iants already often-obscure type error messages! And note that the type def= initions for polymorphic variants would be the other way around from regula= r variants because [> `Foo of int * int ] already means use a tuple. So for= a variant Foo of int * int means flat but for a polymorphic variant `Foo o= f int * int means a tuple. Nice! (and unavoidable - changing that syntax wo= uld break all type annotations for polymorphic variants in existing code) >=20 > In my opinion, it would also be quite hideous to be allowing values of bo= th types to float around. It wouldn't be pretty to have: >=20 > let foo =3D `Foo (1, 2) > and bar =3D `Foo (1, 2) [@explicit_arity] >=20 > giving foo <> bar (and it would be a similarly not nice to introduce a ty= pe-level hack to allow such cases to be equal). It would also allow some of= the already entertaining accidental type errors with functions to include = such horrors as in this contrived example: >=20 > # let f =3D function `Foo (s : string * string) -> fst s > val f : [< `Foo of string * string ] -> string =3D > # let g =3D function `Foo ((fst : string), (_ : string)) [@explicit_arity= ] -> fst;; > val g : [< `Foo of (string * string) ] -> string =3D > # let h b x =3D if b then f x else g x;; > val h : bool -> [< `Foo of string * string & (string * string) ] -> strin= g =3D >=20 > It's already bad enough when these errors arise by accident where the typ= es differ by more than just some brackets! >=20 > So, no - I don't think that the two layouts for polymorphic variants aren= 't available because of time to implement. I think that *because of the lac= k of a concrete type definition for them* (which is the point, after all) t= hat having both layouts would have considerably complicated them for users,= rather than developers.=20 >=20 >> I do wish OCaml used the revised syntax's syntactic distinction between = the two modes which is what I'm >> currently experimenting with. >=20 > However, that argument seems to be long-done (especially with camlp4, whi= ch I believe was the original driving force behind the revised syntax, havi= ng been removed from the official compiler) >=20 >=20 > David >=20