When declaring a module with the same name as a discriminated union type, it is not possible to reference the module from a different source file using a fully qualified name.
Repro steps
Define a type and module in a first source file:
module Domain
type TodoID = TodoID of int
module TodoID = let value (TodoID i) = i
let ti = TodoID 1
let i1 = TodoID.value ti // Works as expected
Try to reference it from a different file using a fully qualified name:
module DTO_broken
let ti = Domain.TodoID 1
let i1 = Domain.TodoID.value ti // error FS0039: The field, constructor or member 'value' is not defined.
let i2 = Domain.TodoIDModule.value ti // error FS0039: The value, constructor, namespace or type 'TodoIDModule' is not defined
Code does not compile.
Known workarounds
Rename the discriminated union or the module.
Related information
Stackoverflow thread: https://stackoverflow.com/a/59974056/5298588
In this thread Asti diagnoses the problem as follows:
The problem is not in generating the module suffix, which it does correctly (IL verified), but type inference assigning a higher visibility to the DU case. If you bring down the visibility,
type private A = A of string
it starts working again. This seems to a problem with the type inference, so it's probably best to refactor the DU case for now and file a bug report.
Provide any related information (optional):
F# 4.7.0
I've been digging in name resolution a lot lately; I'll try to look at this sometime this week.
This is actually "unfortunate but by design" and is related to https://github.com/dotnet/fsharp/issues/9807. It would need an RFC (and perhaps a breaking change) to fix
See my comment here: https://github.com/dotnet/fsharp/issues/9807#issuecomment-679239494
One of the workarounds should be applied.
I have recorded this as a language suggestion here: fsharp/fslang-suggestions#907
Most helpful comment
I've been digging in name resolution a lot lately; I'll try to look at this sometime this week.