question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The `|` symbol is required for single-case generic Discriminated Unions

See original GitHub issue

This is a single-case DU:

type Foo = Foo

However, the | symbol is required for single-case generic DUs.

// Does not compile
type Bar<'t> = Bar 

// Compiles
type Bar<'t> = | Bar 

From StackOverflow:

I think there are two interesting cases here. The first one is:

type Foo = Foo

This looks like a self-referential type alias at first, but that’s not allowed, so the compiler instead accepts it as a valid DU. This is correct, although subtle, behavior.

The second interesting case is:

type Bar<'t> = Bar   // Error: The type 'Bar<_>' expects 1 type argument(s) but is given 0

This also looks like a self-referential type alias at first, but with the wrong number of type parameters. Since the reference is invalid, the compiler issues an error before it has a chance to realize that it’s actually looking at a valid DU definition. I think one could reasonably argue that this is a bug in the compiler, and I suggest submitting it as an issue to the F# compiler team. The expected behavior is that this is a valid DU, just like type Foo = Foo and type Bar<'t> = | Bar.

Note also that the following is (correctly) not allowed:

type Bar<'t> = Bar<'t>   // Error: This type definition involves an immediate cyclic reference through an abbreviation

Expected behavior

These should be equivalent:

type Bar<'t> = Bar 

type Bar<'t> = | Bar 

Actual behavior

This does not compile:

type Bar<'t> = Bar 

Known workarounds

Add the |

Related information

Ubuntu 20.04

dotnet --version
6.0.300

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
charlesroddiecommented, May 26, 2022

The canonical representation of DUs has a vertical line before the first case: type SomeDU = | SomeCase.... See https://github.com/fsharp/fslang-suggestions/issues/958#issuecomment-765381374 . Existing cases where the compiler allows the vertical line to be omitted are unfortunate, and while they currently need to be there for backwards compat, they should be warned about eventually by analyzers.

The fact that it is not obvious whether the code here is a DU or type alias underlines the need to enforce the canonical formatting.

0reactions
dsymecommented, Sep 21, 2022

I’ll close as this can be a language suggestion

Read more comments on GitHub >

github_iconTop Results From Across the Web

Designing with types: Single case union types
The answer is generally the single case discriminated union. It is much easier to “wrap” and “unwrap”, as the “union case” is actually...
Read more >
Discriminated Unions - F# | Microsoft Learn
Discriminated unions provide support for values that can be one of a number of named cases, possibly each with different values and types....
Read more >
Add compiler flag to default to struct representation of ...
I propose we add a flag to opt into struct representation of discriminated unions by default in these two cases where there is...
Read more >
typescript - Discriminated Union of Generic type
The problem. Type narrowing in discriminated unions is subject to several restrictions: No unwrapping of generics.
Read more >
Question about discriminated unions and generics
Suppose I have a discriminated union type "Animal" which is either "Cat" or "Dog" and a generic type "ValidationResult<T>".
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found