Exposing comparison/equality on a private union type
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
Mo开发者_运维问答dule.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 the with ... end
syntax. 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:
// Mod.fs
namespace Mod
[<CustomEquality; CustomComparison>] //; CustomEquality>]
type A<'T when 'T : comparison> =
| A of 'T list
override x.Equals y = compare x (y :?> A<_>) = 0
override x.GetHashCode() = -1
interface System.IComparable with
member x.CompareTo(y) = compare x (y :?> A<_>)
// Mod.fsi
namespace Mod
[<Sealed>]
type A<'T when 'T : comparison> =
interface System.IComparable
override Equals : obj -> bool
override GetHashCode : unit -> int
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:
// Mod.fsi
namespace Mod
type A<'T when 'T : comparison> =
private | A of 'T list
// Mod.fs
namespace Mod
[<StructuralComparisonAttribute; StructuralEqualityAttribute>]
type A<'T when 'T : comparison> =
| A of 'T list
精彩评论