fsharp / fsharp/fslang-suggestions

Allow the union pattern to be implemented explicitly

Open
#1,152 2 comments 20 reactions 0 assignees View on GitHub
area: unions
Dominant language
No language data
Stars
373
Forks
21
PR merge metrics
No merged PRs in 30d

Description

In F#, discriminated unions are a pattern, e.g.

```fsharp
type U = A of value: int | B of value: string
```

generates code containing roughly this public API:
```fsharp
type U =
static member NewA(value: int) = ...
static member NewB(value: string) = ...
member IsA: bool
member IsB: bool
member Tag: int
static type A =
inherit U
member value: int
static type B =
inherit U
member value: string
static type Tags =
| A = 0
| B = 1
```
plus various attributes.

I propose it be possible to implement this pattern explicitly (unchecked) without committing to a representation of the backing data beyond the presence of subtypes A and B of the reference type U, and the presence of `Tag`/`Tags`.

This is quite a large feature:
* there are some variations to consider for single case unions
* there are variations to consider for struct unions
* there will be responses that the pattern is too complex to write by hand. For example people may request that it is possible to omit the `Tag` and `Tags` even if pattern matching over a large number of union cases is slower for these cases (preferring type tests on the input type)
* there will be responses that authoring is not the same as proposed C# unions, which may reduce the utility of the feature
* there will be questions about whether it is possible to use FSharp.Reflection on these types, given this is driven by various additional attributes
* there will be questions about what happens if people get the pattern slightly wrong
* there will be questions about whether this allows https://github.com/fsharp/fslang-suggestions/issues/154
* there will be questions about whether the `Tags` need to form a contiguous `0..n-1` list
* there will be questions about whether the attributes need to be present
* it relies on #277

The existing way of approaching this problem in F# is to accept the default representations for backing data.

## Pros and Cons

The advantages of making this adjustment to F# are that programmers can control the ultimate representation of union types without subsequent consuming code changing and without breaking binary compatibility.

The disadvantages of making this adjustment to F# are that
* it is complex to use (more complex than people will like)
* its use cases are rare
* it may inhibit later development of features for unions

On the whole I feel this is "too costly" to do for the benefits it brings but I am recording the idea here, partly because it clarifies what was meant by #726 and partly because it relates to #154 and #277

## Extra information

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

Related suggestions: https://github.com/fsharp/fslang-suggestions/issues/164 deals with some similar issues for records.

## 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](http://stackoverflow.com)) and I have searched stackoverflow for discussions of this issue
* [ ] I have [searched both open and closed suggestions on this site](http://github.com/fsharp/fslang-suggestions/issues) 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

## For Readers

If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reviewing the dependency on #277 and the related suggestions #154, #726, and #164. The proposal raises unresolved questions about single-case and struct unions, tags, attributes, reflection, and malformed patterns. Done would require an agreed scope and language design before implementation work can begin.

Written by the indexing model from the issue text.

Assessment

Tech stack
fsharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.