caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Explicit Arity with Polymorphic Variants
@ 2015-01-23  6:53 Jordan W
  2015-01-23  8:03 ` Jacques Garrigue
  0 siblings, 1 reply; 11+ messages in thread
From: Jordan W @ 2015-01-23  6:53 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1888 bytes --]

The OCaml compiler allows distinguishing between variants that accept a
single tuple and variant types that accept several parameters. What looks
like a variant type accepting a tuple, is actually the later:

type x = TwoSeparateArguments of int * int
let tuple = (10,10)
let thisWontWork = TwoSeparateArguments tuple;;
>> Error: The constructor TwoSeparateArguments expects 2 argument(s),
                                                           but is applied
here to 1 argument(s)

(* Notice the extra parens around the two ints *)
type x = OneArgumentThatIsATuple of (int * int)
let thisActuallyWorks = OneArgumentThatIsATuple tuple

The extra parens distinguish at type definition time which of the two is
intended.

But OCaml does some automatic massaging of the data that you supply to
constructor values.
let _ = OneArgumentThatIsATuple (4, 5)
let _ = TwoSeparateArguments (4, 5)

No extra parens are required in this case. But OCaml does give you the
ability to annotate patterns and expressions with an "explicit_arity"
attribute which allows syntactic distinction between supplying two separate
parameters vs. one that happens to be a tuple. This is important for other
parser extensions that wish to treat the two distinctly. What OCaml allows
(explicit_arity attribute) works well enough.

The only problem is that there doesn't seem to be a way to utilize the same
explicit_arity attributes with polymorphic variants. Such attributes are
not acknowledged by the type system. Is this intended?

Taking a quick look at typecore.ml, explicit_arity appears to be
acknowledged on standard constructors but not polymorphic variants.
https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml

It seems these should be brought to consistency. I will file a mantis issue
unless anyone believes this is intended.

Thank you in advance.

Jordan

[-- Attachment #2: Type: text/html, Size: 2528 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-23  6:53 [Caml-list] Explicit Arity with Polymorphic Variants Jordan W
@ 2015-01-23  8:03 ` Jacques Garrigue
  2015-01-23  9:04   ` Jordan W
  2015-01-24  3:47   ` Jordan W
  0 siblings, 2 replies; 11+ messages in thread
From: Jacques Garrigue @ 2015-01-23  8:03 UTC (permalink / raw)
  To: Jordan W; +Cc: Mailing List OCaml

The answer is simple: polymorphic variants can only accept one argument
(which may of course be a tuple). The other behavior would have required
a specific syntax for multi-parameter polymorphic variants, since there is
no information associated to the constructor for them.

Jacques Garrigue

On 2015/01/23 15:53, Jordan W wrote:
> 
> The OCaml compiler allows distinguishing between variants that accept a single tuple and variant types that accept several parameters. What looks like a variant type accepting a tuple, is actually the later:
> 
> type x = TwoSeparateArguments of int * int
> let tuple = (10,10)
> let thisWontWork = TwoSeparateArguments tuple;;
> >> Error: The constructor TwoSeparateArguments expects 2 argument(s),                                                                  but is applied here to 1 argument(s)
> 
> (* Notice the extra parens around the two ints *)
> type x = OneArgumentThatIsATuple of (int * int)
> let thisActuallyWorks = OneArgumentThatIsATuple tuple
> 
> The extra parens distinguish at type definition time which of the two is intended.
> 
> But OCaml does some automatic massaging of the data that you supply to constructor values.
> let _ = OneArgumentThatIsATuple (4, 5)
> let _ = TwoSeparateArguments (4, 5)
> 
> No extra parens are required in this case. But OCaml does give you the ability to annotate patterns and expressions with an "explicit_arity" attribute which allows syntactic distinction between supplying two separate parameters vs. one that happens to be a tuple. This is important for other parser extensions that wish to treat the two distinctly. What OCaml allows (explicit_arity attribute) works well enough.
> 
> The only problem is that there doesn't seem to be a way to utilize the same explicit_arity attributes with polymorphic variants. Such attributes are not acknowledged by the type system. Is this intended?
> 
> Taking a quick look at typecore.ml, explicit_arity appears to be acknowledged on standard constructors but not polymorphic variants.
> https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
> 
> It seems these should be brought to consistency. I will file a mantis issue unless anyone believes this is intended.
> 
> Thank you in advance.
> 
> Jordan
> 
> 



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  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-24  3:47   ` Jordan W
  1 sibling, 2 replies; 11+ messages in thread
From: Jordan W @ 2015-01-23  9:04 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: Mailing List OCaml

[-- Attachment #1: Type: text/plain, Size: 2853 bytes --]

My understanding was that this "explicit_arity" attribute allows precisely
that - the capability to implement a specific syntax to distinguish between
multiple arguments and just one argument (that may coincidentally be a
tuple). My question is why this capability is not extended to polymorphic
variants in the same way it has been extended to standard variant types.

On Fri, Jan 23, 2015 at 12:03 AM, Jacques Garrigue <
garrigue@math.nagoya-u.ac.jp> wrote:

> The answer is simple: polymorphic variants can only accept one argument
> (which may of course be a tuple). The other behavior would have required
> a specific syntax for multi-parameter polymorphic variants, since there is
> no information associated to the constructor for them.
>
> Jacques Garrigue
>
> On 2015/01/23 15:53, Jordan W wrote:
> >
> > The OCaml compiler allows distinguishing between variants that accept a
> single tuple and variant types that accept several parameters. What looks
> like a variant type accepting a tuple, is actually the later:
> >
> > type x = TwoSeparateArguments of int * int
> > let tuple = (10,10)
> > let thisWontWork = TwoSeparateArguments tuple;;
> > >> Error: The constructor TwoSeparateArguments expects 2 argument(s),
>                                                               but is
> applied here to 1 argument(s)
> >
> > (* Notice the extra parens around the two ints *)
> > type x = OneArgumentThatIsATuple of (int * int)
> > let thisActuallyWorks = OneArgumentThatIsATuple tuple
> >
> > The extra parens distinguish at type definition time which of the two is
> intended.
> >
> > But OCaml does some automatic massaging of the data that you supply to
> constructor values.
> > let _ = OneArgumentThatIsATuple (4, 5)
> > let _ = TwoSeparateArguments (4, 5)
> >
> > No extra parens are required in this case. But OCaml does give you the
> ability to annotate patterns and expressions with an "explicit_arity"
> attribute which allows syntactic distinction between supplying two separate
> parameters vs. one that happens to be a tuple. This is important for other
> parser extensions that wish to treat the two distinctly. What OCaml allows
> (explicit_arity attribute) works well enough.
> >
> > The only problem is that there doesn't seem to be a way to utilize the
> same explicit_arity attributes with polymorphic variants. Such attributes
> are not acknowledged by the type system. Is this intended?
> >
> > Taking a quick look at typecore.ml, explicit_arity appears to be
> acknowledged on standard constructors but not polymorphic variants.
> >
> https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
> >
> > It seems these should be brought to consistency. I will file a mantis
> issue unless anyone believes this is intended.
> >
> > Thank you in advance.
> >
> > Jordan
> >
> >
>
>
>

[-- Attachment #2: Type: text/html, Size: 3697 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-23  9:04   ` Jordan W
@ 2015-01-23  9:56     ` David Allsopp
  2015-01-24  8:52     ` Gabriel Scherer
  1 sibling, 0 replies; 11+ messages in thread
From: David Allsopp @ 2015-01-23  9:56 UTC (permalink / raw)
  To: Mailing List OCaml

[-- Attachment #1: Type: text/plain, Size: 3412 bytes --]

A regular constructor has a type definition which is where explicit_arity is defined, i.e. it's inferred from either

type t = Foo of int * int

or

type t = Foo of (int * int)

which allows you to determine what Foo(42, 42) actually means.

Polymorphic variants have no type definition so, without a new syntax *for the values*, you can only have one interpretation. Requiring a type definition for polymorphic variants would defeat their purpose!


David



On 23 Jan 2015, at 09:06, Jordan W <jordojw@gmail.com<mailto:jordojw@gmail.com>> wrote:

My understanding was that this "explicit_arity" attribute allows precisely that - the capability to implement a specific syntax to distinguish between multiple arguments and just one argument (that may coincidentally be a tuple). My question is why this capability is not extended to polymorphic variants in the same way it has been extended to standard variant types.

On Fri, Jan 23, 2015 at 12:03 AM, Jacques Garrigue <garrigue@math.nagoya-u.ac.jp<mailto:garrigue@math.nagoya-u.ac.jp>> wrote:
The answer is simple: polymorphic variants can only accept one argument
(which may of course be a tuple). The other behavior would have required
a specific syntax for multi-parameter polymorphic variants, since there is
no information associated to the constructor for them.

Jacques Garrigue

On 2015/01/23 15:53, Jordan W wrote:
>
> The OCaml compiler allows distinguishing between variants that accept a single tuple and variant types that accept several parameters. What looks like a variant type accepting a tuple, is actually the later:
>
> type x = TwoSeparateArguments of int * int
> let tuple = (10,10)
> let thisWontWork = TwoSeparateArguments tuple;;
> >> Error: The constructor TwoSeparateArguments expects 2 argument(s),                                                                  but is applied here to 1 argument(s)
>
> (* Notice the extra parens around the two ints *)
> type x = OneArgumentThatIsATuple of (int * int)
> let thisActuallyWorks = OneArgumentThatIsATuple tuple
>
> The extra parens distinguish at type definition time which of the two is intended.
>
> But OCaml does some automatic massaging of the data that you supply to constructor values.
> let _ = OneArgumentThatIsATuple (4, 5)
> let _ = TwoSeparateArguments (4, 5)
>
> No extra parens are required in this case. But OCaml does give you the ability to annotate patterns and expressions with an "explicit_arity" attribute which allows syntactic distinction between supplying two separate parameters vs. one that happens to be a tuple. This is important for other parser extensions that wish to treat the two distinctly. What OCaml allows (explicit_arity attribute) works well enough.
>
> The only problem is that there doesn't seem to be a way to utilize the same explicit_arity attributes with polymorphic variants. Such attributes are not acknowledged by the type system. Is this intended?
>
> Taking a quick look at typecore.ml<http://typecore.ml>, explicit_arity appears to be acknowledged on standard constructors but not polymorphic variants.
> https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
>
> It seems these should be brought to consistency. I will file a mantis issue unless anyone believes this is intended.
>
> Thank you in advance.
>
> Jordan
>
>




[-- Attachment #2: Type: text/html, Size: 4876 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-23  8:03 ` Jacques Garrigue
  2015-01-23  9:04   ` Jordan W
@ 2015-01-24  3:47   ` Jordan W
  2015-01-24  8:24     ` David Allsopp
  1 sibling, 1 reply; 11+ messages in thread
From: Jordan W @ 2015-01-24  3:47 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: Mailing List OCaml

[-- Attachment #1: Type: text/plain, Size: 3916 bytes --]

David Allsopp, could you please include me on the "Reply" so that the mail
threads make their way to my inbox?

David, are you certain that the explicit_arity attribute is only related to
type declarations? I do not believe that to be the case. I understand them
to apply to patterns and expressions as well.

(* Declares a variant that accepts a *single* parameter *)
type oneArgTuple = OneArg of (int*int)

(* Works because arity is massaged into whatever is necessary and doesn't
need to be expressed at parse time. *)
let OneArg (x,y) = OneArg (1,2)

(* But you can *explicitly* enforce arity and tell the type system that
this tuple should be treated as multiple arguments *)
(* That causes this to fail type checking on this tuple pattern! *)
let (OneArg (x,y) [@explicit_arity]) = OneArg (1,2);;
>> Error: The constructor OneArg expects 1 argument(s),
>> but is applied here to 2 argument(s)

(* Similarly, at parse time, you can tell the parser to parse an expression
as being multiple arguments *)
let result = OneArg (1,2)[@explicit_arity];;
>> Error: The constructor OneArg expects 1 argument(s),
>> but is applied here to 2 argument(s)

So the fact that you can inform the parser to treat a tuple as multiple
arguments to a Constructor, means that the same should be true of
polymorphic variants, but it is not. For example, this type checks but it
shouldn't:

 let (`MyThing (x,y) [@explicit_arity]) = `MyThing (2,2);;

On Fri, Jan 23, 2015 at 12:03 AM, Jacques Garrigue <
garrigue@math.nagoya-u.ac.jp> wrote:

> The answer is simple: polymorphic variants can only accept one argument
> (which may of course be a tuple). The other behavior would have required
> a specific syntax for multi-parameter polymorphic variants, since there is
> no information associated to the constructor for them.
>
> Jacques Garrigue
>
> On 2015/01/23 15:53, Jordan W wrote:
> >
> > The OCaml compiler allows distinguishing between variants that accept a
> single tuple and variant types that accept several parameters. What looks
> like a variant type accepting a tuple, is actually the later:
> >
> > type x = TwoSeparateArguments of int * int
> > let tuple = (10,10)
> > let thisWontWork = TwoSeparateArguments tuple;;
> > >> Error: The constructor TwoSeparateArguments expects 2 argument(s),
>                                                               but is
> applied here to 1 argument(s)
> >
> > (* Notice the extra parens around the two ints *)
> > type x = OneArgumentThatIsATuple of (int * int)
> > let thisActuallyWorks = OneArgumentThatIsATuple tuple
> >
> > The extra parens distinguish at type definition time which of the two is
> intended.
> >
> > But OCaml does some automatic massaging of the data that you supply to
> constructor values.
> > let _ = OneArgumentThatIsATuple (4, 5)
> > let _ = TwoSeparateArguments (4, 5)
> >
> > No extra parens are required in this case. But OCaml does give you the
> ability to annotate patterns and expressions with an "explicit_arity"
> attribute which allows syntactic distinction between supplying two separate
> parameters vs. one that happens to be a tuple. This is important for other
> parser extensions that wish to treat the two distinctly. What OCaml allows
> (explicit_arity attribute) works well enough.
> >
> > The only problem is that there doesn't seem to be a way to utilize the
> same explicit_arity attributes with polymorphic variants. Such attributes
> are not acknowledged by the type system. Is this intended?
> >
> > Taking a quick look at typecore.ml, explicit_arity appears to be
> acknowledged on standard constructors but not polymorphic variants.
> >
> https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
> >
> > It seems these should be brought to consistency. I will file a mantis
> issue unless anyone believes this is intended.
> >
> > Thank you in advance.
> >
> > Jordan
> >
> >
>
>
>

[-- Attachment #2: Type: text/html, Size: 5112 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-24  3:47   ` Jordan W
@ 2015-01-24  8:24     ` David Allsopp
  0 siblings, 0 replies; 11+ messages in thread
From: David Allsopp @ 2015-01-24  8:24 UTC (permalink / raw)
  To: Mailing List OCaml; +Cc: Jordan W

Jordan W wrote:
> David, are you certain that the explicit_arity attribute is only related to type 
> declarations? I do not believe that to be the case. I understand them to apply to
> patterns and expressions as well.

I'm (reasonably) certain that the information it conveys can only ever be useful when you have a type definition. 

> (* Declares a variant that accepts a *single* parameter *)
> type oneArgTuple = OneArg of (int*int)
>
> (* Works because arity is massaged into whatever is necessary and doesn't need to be expressed at parse time. *)
> let OneArg (x,y) = OneArg (1,2)

Because of the type definition. 

> (* But you can *explicitly* enforce arity and tell the type system that this tuple should be treated as multiple arguments *)
> (* That causes this to fail type checking on this tuple pattern! *)
> let (OneArg (x,y) [@explicit_arity]) = OneArg (1,2);;
> >> Error: The constructor OneArg expects 1 argument(s),
> >> but is applied here to 2 argument(s)

Again, because of the presence of a type definition.

> (* Similarly, at parse time, you can tell the parser to parse an expression as being multiple arguments *)
> let result = OneArg (1,2)[@explicit_arity];;
> >> Error: The constructor OneArg expects 1 argument(s),
> >> but is applied here to 2 argument(s)
>
> So the fact that you can inform the parser to treat a tuple as multiple arguments to a Constructor, 
> means that the same should be true of polymorphic variants, but it is not. For example, this type 
> checks but it shouldn't:
>
> let (`MyThing (x,y) [@explicit_arity]) = `MyThing (2,2);;

In this context, if the type-checker chose to look at the @explicit_arity attribute, then it must always return a type error when the tuple is neither singleton nor unit (since polymorphic variants only take one argument) - what's the benefit of this, therefore? (I don't quite follow why you'd want to be getting an explicit type check error when using an *internal* OCaml attribute somewhere where it's not intended - http://caml.inria.fr/svn/ocaml/branches/constructors_with_record3/experimental/frisch/extension_points.txt).


David

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  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
  1 sibling, 1 reply; 11+ messages in thread
From: Gabriel Scherer @ 2015-01-24  8:52 UTC (permalink / raw)
  To: Jordan W; +Cc: Jacques Garrigue, Mailing List OCaml

explicit_arity is an ugly hack. It is used by camlp[45] (whose revised
syntax has a superior currified constructor-parameter syntax and is
thus never confused about arities) to convert its internal AST into
the OCaml parse tree. It is not meant to be used by end-users, only by
camlp5 as a code-producing tool.

You ask why this was not extended to polymorphic variant. There was no
need, so nobody worked on it. Besides, I suspect making polymorphic
variant more complex is a bad idea -- and am quite certain relying on
an attribute there is a bad idea.


On Fri, Jan 23, 2015 at 10:04 AM, Jordan W <jordojw@gmail.com> wrote:
> My understanding was that this "explicit_arity" attribute allows precisely
> that - the capability to implement a specific syntax to distinguish between
> multiple arguments and just one argument (that may coincidentally be a
> tuple). My question is why this capability is not extended to polymorphic
> variants in the same way it has been extended to standard variant types.
>
> On Fri, Jan 23, 2015 at 12:03 AM, Jacques Garrigue
> <garrigue@math.nagoya-u.ac.jp> wrote:
>>
>> The answer is simple: polymorphic variants can only accept one argument
>> (which may of course be a tuple). The other behavior would have required
>> a specific syntax for multi-parameter polymorphic variants, since there is
>> no information associated to the constructor for them.
>>
>> Jacques Garrigue
>>
>> On 2015/01/23 15:53, Jordan W wrote:
>> >
>> > The OCaml compiler allows distinguishing between variants that accept a
>> > single tuple and variant types that accept several parameters. What looks
>> > like a variant type accepting a tuple, is actually the later:
>> >
>> > type x = TwoSeparateArguments of int * int
>> > let tuple = (10,10)
>> > let thisWontWork = TwoSeparateArguments tuple;;
>> > >> Error: The constructor TwoSeparateArguments expects 2 argument(s),
>> > >> but is applied here to 1 argument(s)
>> >
>> > (* Notice the extra parens around the two ints *)
>> > type x = OneArgumentThatIsATuple of (int * int)
>> > let thisActuallyWorks = OneArgumentThatIsATuple tuple
>> >
>> > The extra parens distinguish at type definition time which of the two is
>> > intended.
>> >
>> > But OCaml does some automatic massaging of the data that you supply to
>> > constructor values.
>> > let _ = OneArgumentThatIsATuple (4, 5)
>> > let _ = TwoSeparateArguments (4, 5)
>> >
>> > No extra parens are required in this case. But OCaml does give you the
>> > ability to annotate patterns and expressions with an "explicit_arity"
>> > attribute which allows syntactic distinction between supplying two separate
>> > parameters vs. one that happens to be a tuple. This is important for other
>> > parser extensions that wish to treat the two distinctly. What OCaml allows
>> > (explicit_arity attribute) works well enough.
>> >
>> > The only problem is that there doesn't seem to be a way to utilize the
>> > same explicit_arity attributes with polymorphic variants. Such attributes
>> > are not acknowledged by the type system. Is this intended?
>> >
>> > Taking a quick look at typecore.ml, explicit_arity appears to be
>> > acknowledged on standard constructors but not polymorphic variants.
>> >
>> > https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
>> >
>> > It seems these should be brought to consistency. I will file a mantis
>> > issue unless anyone believes this is intended.
>> >
>> > Thank you in advance.
>> >
>> > Jordan
>> >
>> >
>>
>>
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-24  8:52     ` Gabriel Scherer
@ 2015-01-25  8:02       ` Jordan W
  2015-01-25 10:11         ` David Allsopp
  0 siblings, 1 reply; 11+ messages in thread
From: Jordan W @ 2015-01-25  8:02 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: Jacques Garrigue, Mailing List OCaml

[-- Attachment #1: Type: text/plain, Size: 5233 bytes --]

It sounds like this has nothing to do with polymorphic variants not
requiring a type definition.

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)?
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.

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).

I do wish OCaml used the revised syntax's syntactic distinction between the
two modes which is what I'm currently experimenting with.

On Sat, Jan 24, 2015 at 12:52 AM, Gabriel Scherer <gabriel.scherer@gmail.com
> wrote:

> explicit_arity is an ugly hack. It is used by camlp[45] (whose revised
> syntax has a superior currified constructor-parameter syntax and is
> thus never confused about arities) to convert its internal AST into
> the OCaml parse tree. It is not meant to be used by end-users, only by
> camlp5 as a code-producing tool.
>
> You ask why this was not extended to polymorphic variant. There was no
> need, so nobody worked on it. Besides, I suspect making polymorphic
> variant more complex is a bad idea -- and am quite certain relying on
> an attribute there is a bad idea.
>
>
> On Fri, Jan 23, 2015 at 10:04 AM, Jordan W <jordojw@gmail.com> wrote:
> > My understanding was that this "explicit_arity" attribute allows
> precisely
> > that - the capability to implement a specific syntax to distinguish
> between
> > multiple arguments and just one argument (that may coincidentally be a
> > tuple). My question is why this capability is not extended to polymorphic
> > variants in the same way it has been extended to standard variant types.
> >
> > On Fri, Jan 23, 2015 at 12:03 AM, Jacques Garrigue
> > <garrigue@math.nagoya-u.ac.jp> wrote:
> >>
> >> The answer is simple: polymorphic variants can only accept one argument
> >> (which may of course be a tuple). The other behavior would have required
> >> a specific syntax for multi-parameter polymorphic variants, since there
> is
> >> no information associated to the constructor for them.
> >>
> >> Jacques Garrigue
> >>
> >> On 2015/01/23 15:53, Jordan W wrote:
> >> >
> >> > The OCaml compiler allows distinguishing between variants that accept
> a
> >> > single tuple and variant types that accept several parameters. What
> looks
> >> > like a variant type accepting a tuple, is actually the later:
> >> >
> >> > type x = TwoSeparateArguments of int * int
> >> > let tuple = (10,10)
> >> > let thisWontWork = TwoSeparateArguments tuple;;
> >> > >> Error: The constructor TwoSeparateArguments expects 2 argument(s),
> >> > >> but is applied here to 1 argument(s)
> >> >
> >> > (* Notice the extra parens around the two ints *)
> >> > type x = OneArgumentThatIsATuple of (int * int)
> >> > let thisActuallyWorks = OneArgumentThatIsATuple tuple
> >> >
> >> > The extra parens distinguish at type definition time which of the two
> is
> >> > intended.
> >> >
> >> > But OCaml does some automatic massaging of the data that you supply to
> >> > constructor values.
> >> > let _ = OneArgumentThatIsATuple (4, 5)
> >> > let _ = TwoSeparateArguments (4, 5)
> >> >
> >> > No extra parens are required in this case. But OCaml does give you the
> >> > ability to annotate patterns and expressions with an "explicit_arity"
> >> > attribute which allows syntactic distinction between supplying two
> separate
> >> > parameters vs. one that happens to be a tuple. This is important for
> other
> >> > parser extensions that wish to treat the two distinctly. What OCaml
> allows
> >> > (explicit_arity attribute) works well enough.
> >> >
> >> > The only problem is that there doesn't seem to be a way to utilize the
> >> > same explicit_arity attributes with polymorphic variants. Such
> attributes
> >> > are not acknowledged by the type system. Is this intended?
> >> >
> >> > Taking a quick look at typecore.ml, explicit_arity appears to be
> >> > acknowledged on standard constructors but not polymorphic variants.
> >> >
> >> >
> https://github.com/ocaml/ocaml/blob/6e85c2d956c8fd5b45acd70a27586e44bb3a3119/typing/typecore.ml
> >> >
> >> > It seems these should be brought to consistency. I will file a mantis
> >> > issue unless anyone believes this is intended.
> >> >
> >> > Thank you in advance.
> >> >
> >> > Jordan
> >> >
> >> >
> >>
> >>
> >
>

[-- Attachment #2: Type: text/html, Size: 7025 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-25  8:02       ` Jordan W
@ 2015-01-25 10:11         ` David Allsopp
  2015-01-25 19:57           ` Jordo
  0 siblings, 1 reply; 11+ messages in thread
From: David Allsopp @ 2015-01-25 10:11 UTC (permalink / raw)
  To: Mailing List OCaml; +Cc: Jordan W

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


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-25 10:11         ` David Allsopp
@ 2015-01-25 19:57           ` Jordo
  2015-01-26  4:05             ` Jacques Garrigue
  0 siblings, 1 reply; 11+ messages in thread
From: Jordo @ 2015-01-25 19:57 UTC (permalink / raw)
  To: David Allsopp; +Cc: Mailing List OCaml

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
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Explicit Arity with Polymorphic Variants
  2015-01-25 19:57           ` Jordo
@ 2015-01-26  4:05             ` Jacques Garrigue
  0 siblings, 0 replies; 11+ messages in thread
From: Jacques Garrigue @ 2015-01-26  4:05 UTC (permalink / raw)
  To: Jordo; +Cc: David Allsopp, OCaml Mailing List

On 2015/01/26 04:57, Jordo wrote:
> 
> 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.


Indeed, there is no theoretical difficulty in introducing multi-argument polymorphic variants, and they were considered at some point.
However, for this to work this should imperatively be supported at the type level too: multi-argument polymorphic variant should have a type incompatible with single-argument ones.
So this means making the type algebra more complex, adding extra syntax both at the value/pattern and type level, and extending the unification and type inference algorithms, for something that doesn't seem that useful (if you need performance, you're better served by normal variants anyway).
Of course you're free to try to add them to the compiler :-)

	Jacques

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-01-26  4:06 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-23  6:53 [Caml-list] Explicit Arity with Polymorphic Variants 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
2015-01-26  4:05             ` Jacques Garrigue
2015-01-24  3:47   ` Jordan W
2015-01-24  8:24     ` David Allsopp

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).