Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the `|` mean in a single case DU?

Tags:

f#

Consider this DU:

type Foo = | Foo

My understanding was that this is equivalent:

type Foo = Foo

However, if we introduce generics they are not:

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

What's going on here?


More discoveries:

// Works
type Bar<'t> = Bar of 't
// Works
type Bar<'t> = | Bar of 't
like image 331
sdgfsdh Avatar asked Nov 01 '25 10:11

sdgfsdh


1 Answers

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

The compiler source-code has the following to say:

// This unfortunate case deals with "type x = A" 
// In F# this only defines a new type if A is not in scope 
// as a type constructor, or if the form type A = A is used. 
// "type x = | A" can always be used instead. 
like image 58
Brian Berns Avatar answered Nov 04 '25 21:11

Brian Berns



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!