New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make the argument n-ary constructor behave as a tuple #6455
Comments
Comment author: @mshinwell 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.) |
Comment author: @alainfrisch 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. |
Comment author: @mshinwell Ah, that's true, we'll be stymied by the comparison code. That's unfortunate. |
Comment author: ybarnoy 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. |
Comment author: @alainfrisch 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). |
Comment author: ybarnoy 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. |
Comment author: Bardou What about (B) or #B to mean "curried B"? |
Comment author: @alainfrisch 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. |
Comment author: @alainfrisch Uploaded a second version which improves the error messages at the cost of type-checking twice the argument of the constructor. |
Comment author: @alainfrisch 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. |
Comment author: @alainfrisch Also implemented the pattern side. Time to switch to github: https://github.com/alainfrisch/ocaml/tree/tuple_constructors |
Comment author: @alainfrisch See the discussion on Github. |
Original bug ID: 6455
Reporter: @alainfrisch
Status: closed (set by @alainfrisch on 2015-11-12T14:38:05Z)
Resolution: won't fix
Priority: normal
Severity: feature
Category: typing
Monitored by: @diml @ygrek Bardou @jmeber @yallop @hcarty
Bug description
Since 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.
File attachments
The text was updated successfully, but these errors were encountered: