caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jordo <jordojw@gmail.com>
To: David Allsopp <dra-news@metastack.com>
Cc: Mailing List OCaml <caml-list@inria.fr>
Subject: Re: [Caml-list] Explicit Arity with Polymorphic Variants
Date: Sun, 25 Jan 2015 11:57:41 -0800	[thread overview]
Message-ID: <02B4AAD3-9AD1-42F8-BDCA-FFAA7EA43F03@gmail.com> (raw)
In-Reply-To: <E51C5B015DBD1348A1D85763337FB6D9E9895A6C@Remus.metastack.local>

You've listed some good examples of why this would be difficult to implement 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 variants cannot assume two forms - each incompatible with the other, with any particular 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 would be incompatible with each other at the type level just as they are incompatible for standard variants. My question was why does a distinction at the type level require a type *definition* (which was your original claim). For the sake of experimentation, assume you can create any syntax you need that would unambiguously express which of the two forms is being reasoned about in all situations.

The fact that this is been attempted before (revised syntax) without much success or adoption doesn't discourage me from experimenting with it again to learn about the internals of variants.

Jordan W

Sent from my iPhone

> On Jan 25, 2015, at 2:11 AM, David Allsopp <dra-news@metastack.com> wrote:
> 
> Jordan W wrote:
>> It sounds like this has nothing to do with polymorphic variants
>> not requiring a type definition.
> 
> No, it still has everything to do with it! (I'm not sure I agree with Gabriel'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!).
> 
>> 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 
>> argument tuple constructors and mult-argument constructors:
>> 
>> 1. Memory layout is different (Is this still the case)?
> 
> Yes - for the tuple case, the standard variant is a block of size one pointing 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 number from the type definition.
> 
>> 2. First-classness of arguments is different. With a single argument 
>> tuple, the contents can be passed around and then finally placed into 
>> the constructor without any overhead of destructuring/restructuring.
> 
> The destructuring is almost always useful, I think? I can't imagine a case where not being able to match on just the tuple is something you'd want to avoid. The reason for having the two layouts for standard variants is because 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.
> 
> For polymorphic variants, where there's no type definition, it makes sense that the tuple version is the layout for the same reason - especially as polymorphic variants are less memory-efficient than standard variants anyway.
> 
>> Both of these seem like desirable controls to have and possibly justifies
>> the existence of having two modes. Under that assumption, having some way 
>> to designate in the parse tree which is intended (at the pattern or expression
>> level) seems like a good idea - and even if that mechanism is the ugly 
>> `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 polymorphic 
>> variants (even if that is also a hack). Are you saying it was simply because 
>> time has not permitted it? Looking deeper, it seems polymorphic variants are 
>> incapable of accepting multiple arguments and only ever accept a single tuple 
>> (which is therefore allowed to be first class).
> 
> You can't have both memory layouts for polymorphic variants without having a type annotation to distinguish between them. Suppose you have what you want, and [@explicit_arity] is the way to create them:
> 
> Normal tuple case:
> 
> # `Foo (1, 2);;
> - : [> `Foo of (int * int) ] = `Foo (1, 2)
> 
> Proposed flat case:
> 
> # `Foo(1, 2) [@explicit_arity];;
> - : [> `Foo of int * int ] = `Foo (1, 2)
> 
> So that introduces another level of obscure complexity to polymorphic variants already often-obscure type error messages! And note that the type definitions for polymorphic variants would be the other way around from regular 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 of int * int means a tuple. Nice! (and unavoidable - changing that syntax would break all type annotations for polymorphic variants in existing code)
> 
> In my opinion, it would also be quite hideous to be allowing values of both types to float around. It wouldn't be pretty to have:
> 
> let foo = `Foo (1, 2)
> and bar = `Foo (1, 2) [@explicit_arity]
> 
> giving foo <> bar (and it would be a similarly not nice to introduce a type-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:
> 
> # let f = function `Foo (s : string * string) -> fst s
> val f : [< `Foo of string * string ] -> string = <fun>
> # let g = function `Foo ((fst : string), (_ : string)) [@explicit_arity] -> fst;;
> val g : [< `Foo of (string * string) ] -> string = <fun>
> # let h b x = if b then f x else g x;;
> val h : bool -> [< `Foo of string * string & (string * string) ] -> string = <fun>
> 
> It's already bad enough when these errors arise by accident where the types differ by more than just some brackets!
> 
> 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 lack of a concrete type definition for them* (which is the point, after all) that having both layouts would have considerably complicated them for users, rather than developers. 
> 
>> I do wish OCaml used the revised syntax's syntactic distinction between the two modes which is what I'm
>> currently experimenting with.
> 
> However, that argument seems to be long-done (especially with camlp4, which I believe was the original driving force behind the revised syntax, having been removed from the official compiler)
> 
> 
> David
> 

  reply	other threads:[~2015-01-25 19:57 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-23  6:53 Jordan W
2015-01-23  8:03 ` Jacques Garrigue
2015-01-23  9:04   ` Jordan W
2015-01-23  9:56     ` David Allsopp
2015-01-24  8:52     ` Gabriel Scherer
2015-01-25  8:02       ` Jordan W
2015-01-25 10:11         ` David Allsopp
2015-01-25 19:57           ` Jordo [this message]
2015-01-26  4:05             ` Jacques Garrigue
2015-01-24  3:47   ` Jordan W
2015-01-24  8:24     ` David Allsopp

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=02B4AAD3-9AD1-42F8-BDCA-FFAA7EA43F03@gmail.com \
    --to=jordojw@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=dra-news@metastack.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).