Skip to content
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

Allow variable patterns for tuples in Discriminated Union matching #743

Open
Happypig375 opened this issue Jun 4, 2019 · 4 comments

Comments

Projects
None yet
5 participants
@Happypig375
Copy link
Contributor

commented Jun 4, 2019

Allow variable patterns in Discriminated Union matching

I propose we allow variable patterns in Discriminated Union matching

The existing way of approaching this problem in F# is explicitly matching all tuple elements.

type DU = DUCase of int * int * int
match du with
| DUCase tuple -> f tuple

vs

type DU = DUCase of int * int * int
match du with
| DUCase (a, b, c) -> f (a, b, c)

Pros and Cons

The advantage of making this adjustment to F# is shorter and concise matching.

The disadvantage of making this adjustment to F# is implementation effort required.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): XS~S

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@gusty

This comment has been minimized.

Copy link

commented Jun 4, 2019

I don't know what's reason why this was not allowed from the beginning, I wonder whether this is a bug.
Maybe someone would argue that you need to be explicit about the tuple to allow to disambiguate between different tuples, but you can't have 2 cases of the same DU, so what's the point of forcing you to match each element?

@charlesroddie

This comment has been minimized.

Copy link

commented Jun 5, 2019

I agree this would be good to have. Some subtleties:

type DUTuple = DUTupleCase of (int * int)
function
| DUTupleCase data -> ...

Here data has type int*int. This works currently and achieves the objective of the example in the OP.

Now consider:

type DUB =
    | DUBCase1 of int * int
    | DUBCase2 of int * b:int
function
| DUBCase1 case1Data -> ...
| DUBCase2 case2Data -> ...

What type should case2Data have? We should forget DUBCase1 because it's bad practice to have multiple unnamed inputs. We should make a decision for DUBCase2 and extend it consistently to DUBCase1.

The natural type for case2Data is an anonymous record, {| Item1:int; b:int |}. This is currently inconsistent with existing syntax match ... with | DUBCase1(a,b) since (a,b) can't match an anonymous record. But maybe it should be able to match an anonymous record? @cartermp

The other option is to strip the names and match as tuples. So case2Data would have type int * int.

@jwosty

This comment has been minimized.

Copy link
Contributor

commented Jun 5, 2019

@charlesroddie this would be interesting if there were named tuples (i.e. C#'s named ValueTuples); then it would be a 1-to-1 mapping.

Pros: allows this match rule to work
Cons: we already have anonymous records -- what would be the difference?

Just a thought.

Barring either of those, I'm fine with it binding to a plain old tuple. That would not be unexpected to me.

@cartermp

This comment has been minimized.

Copy link
Member

commented Jun 5, 2019

The asymmetry between:

match .. with | DUBCase1(a, b) -> ...// do stuff with 'a' and 'b'

and:

match .. with | DUBCase2 x -> ...// do stuff with 'x.Item' and 'x.b'

Is confusing, since both are currently tuples. If DUBCase2 were defined as an anonymous record type that would make sense. The most consistent form would be to bind both to a tuple type and force the programmer to pattern match if they need to access constituent parts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.