I am struggling to expose comparison/equality on a union type whose cases are hidden. This is what I started with:
Module.FSI
type A<'T when 'T : comparison>
Module.FS
type A<'T when 'T : comparison> = A of 'T list
Program.FS
[<StructuralEquality;StructuralComparison>]
type B =
| Case1
| Case2 of Module.A<char>
But I get the error:
The struct, record or union type 'B' has the 'StructuralComparison'
attribute but the component type 'Module.A<char>' does not satisfy the
'comparison' constraint
I’ve tried using custom equality on A:
Module.FSI
[<CustomEquality;CustomComparison>]
type A<'T when 'T : comparison>
with
interface System.IComparable
override Equals : y:obj -> bool
override GetHashCode : unit -> int
end
Module.FS
[<CustomEquality;CustomComparison>]
type A<'T when 'T : comparison> = A of 'T list
with
override x.Equals y = ...
override x.GetHashCode() = ...
interface System.IComparable with
member x.CompareTo(y) = ...
But I get this:
This construct is deprecated: The syntax 'type X with ...' is reserved
for augmentations. Types whose representations are hidden but which have
members are now declared in signatures using 'type X = ...'.
Is this the right way to go about exposing comparison from an union type with private cases? What is the correct syntax for this in signature files?
The error message only says that the correct syntax for the FSI file declarations should use
=(as in the implementation file) instead of thewith ... endsyntax. However, that doesn’t really solve the problem. After some experimantations, I think you don’t need to apply the attributes in the FSI file:This should do the trick – unfortunatelly, I’m not sure if there is a way to use automatically generated structural equality and hide the implementation of the discriminated union at the same time.
EDIT It looks like you can specify the discriminated union cases in the FSI file, but mark them as
private, so they won’t be visible outside of the module. So maybe this would work too: