开发者

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    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜