Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006455OCamlOCaml typingpublic2014-06-11 10:412015-11-12 15:38
Assigned To 
PrioritynormalSeverityfeatureReproducibilityhave not tried
StatusclosedResolutionwon't fix 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0006455: Make the argument n-ary constructor behave as a tuple
DescriptionSince we use the tuple syntax for n-ary constructors:

  type t = A of int * int

it would make sense to let the user manipulate the argument as a real tuple:

  let f = function A x -> (x : int * int)
  let g x = A x

In general, one needs to copy the constructor fields into a fresh tuple, or the opposite. (The case where the n-ary constructor has tag 0 could be optimized to avoid allocations in [f] and [g].)

One argument against this could be that this proposal hides an allocation when the tuple is extracted from the n-ary constructor. But this is not really different from extracting a float from a float record.

TagsNo tags attached.
Attached Filesdiff file icon tuple_cstr_arg.diff [^] (1,663 bytes) 2015-11-09 12:48 [Show Content]
diff file icon tuple_cstr_arg_2.diff [^] (2,878 bytes) 2015-11-09 13:02 [Show Content]
diff file icon tuple_cstr_arg_3.diff [^] (3,696 bytes) 2015-11-09 15:07 [Show Content]

- Relationships

-  Notes
shinwell (developer)
2014-06-11 10:46

Does it actually matter if the tuple has the "wrong" tag? (It isn't clear to me what we gain by insisting they have tag zero. Likewise for records, I suppose, if you think about the proposal to have records in constructor arguments.)
frisch (developer)
2014-06-11 10:49


type t = A of int | B of int * int

let f = function B x -> x = (0, 0) | A -> false

If you want [f] to behave as expected, you need to ensure that the extracted tuple (x) has the tag 0.
shinwell (developer)
2014-06-11 11:03

Ah, that's true, we'll be stymied by the comparison code. That's unfortunate.
ybarnoy (reporter)
2014-06-11 15:19
edited on: 2014-06-11 15:20

I'd be more interested in a function direction, similar to haskell:

type t = A of int | B of int * int

(A is of type int -> t, B is of type int -> int -> t)

which we could then curry, by writing for example let x = B 4

The cool thing is, that unlike haskell where they couldn't generalize this over to records properly, we can using labels:

type t = A of {x:int} | B of {x:int; y:int}

(A is of type x:int -> t, B is of type x:int -> y:int -> t

So maybe the proper way to do inline records in constructors is B ~x:3 ~y:2?

EDIT: of course we'd have to be backwards compatible, so the form A(3, 4) would feed the whole 'tuple' into A for the first example.

frisch (developer)
2014-06-11 15:54

I don't think it is a good direction to allow:

  let x = B 4

after a definition such as:

  type t = B of int * int

because we still need to support:

  let x = B (1, 2)

Which type would you give to "fun x -> B x"?

Currying is very much at odds with the current syntax for n-ary constructors...

What could make sense is to consider a non-constant constructor as a well-typed functional value. I.e. B would have type (int * int) -> t. This is independent from both the current topic (and the one on inlined records), although it goes into the same direction of making similar syntax behave in a similar way (combining the two: "B (x, y)" would be interpreted as the application of the "B" function to a tuple argument).
ybarnoy (reporter)
2014-06-11 16:15

OK that's a good point -- we can't really support currying syntax at the same time as tuple syntax. I wish we could just have a compiler switch to switch to a new constructor syntax, and leave tuple constructors in the past. We'd then use a pragma to switch the feature on per-file, and eventually deprecate the old way. I really like the way record-like constructors could map onto labels. Anyway, sorry for the tangent.
Bardou (reporter)
2014-06-11 16:33

What about (B) or #B to mean "curried B"?
frisch (developer)
2015-11-09 12:49

Upload a small patch to implement the proposal in expressions (not patterns). The implementation strategy can lead to misleading error message (example in the patch). A better solution would involve a tighter integration with the type-checking logic.
frisch (developer)
2015-11-09 13:03

Uploaded a second version which improves the error messages at the cost of type-checking twice the argument of the constructor.
frisch (developer)
2015-11-09 15:10

Uploaded a third version which delays the expansion into the Typedtree->Lambda phase. This is better since it keeps the Typedtree AST more faithful to the original code. A simple optimization would be to avoid copying the tuple when the constructor has tag 0.
frisch (developer)
2015-11-09 15:35

Also implemented the pattern side. Time to switch to github: [^]
frisch (developer)
2015-11-12 15:38

See the discussion on Github.

- Issue History
Date Modified Username Field Change
2014-06-11 10:41 frisch New Issue
2014-06-11 10:42 frisch Severity minor => feature
2014-06-11 10:46 shinwell Note Added: 0011729
2014-06-11 10:46 shinwell Status new => acknowledged
2014-06-11 10:49 frisch Note Added: 0011731
2014-06-11 11:03 shinwell Note Added: 0011732
2014-06-11 15:19 ybarnoy Note Added: 0011733
2014-06-11 15:20 ybarnoy Note Edited: 0011733 View Revisions
2014-06-11 15:54 frisch Note Added: 0011736
2014-06-11 16:15 ybarnoy Note Added: 0011737
2014-06-11 16:33 Bardou Note Added: 0011739
2015-11-09 12:48 frisch File Added: tuple_cstr_arg.diff
2015-11-09 12:49 frisch Note Added: 0014659
2015-11-09 13:02 frisch File Added: tuple_cstr_arg_2.diff
2015-11-09 13:03 frisch Note Added: 0014660
2015-11-09 15:07 frisch File Added: tuple_cstr_arg_3.diff
2015-11-09 15:10 frisch Note Added: 0014661
2015-11-09 15:35 frisch Note Added: 0014662
2015-11-12 15:38 frisch Note Added: 0014665
2015-11-12 15:38 frisch Status acknowledged => closed
2015-11-12 15:38 frisch Resolution open => won't fix

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker