2011-06-05 98 views
2

我很努力在隐藏了个案的union类型上暴露比较/等号。这是我开始:在私有union类型上暴露比较/等号

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> 

但我得到的错误:

The struct, record or union type 'B' has the 'StructuralComparison' 
attribute but the component type 'Module.A<char>' does not satisfy the 
'comparison' constraint 

我使用自定义平等试穿答:

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) = ... 

但我得到这个:

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 = ...'. 

是这是揭示工会与私人银行比较的正确方法ES?签名文件中的正确语法是什么?

回答

2

错误消息只说FSI文件声明的正确语法应该使用=(如在实现文件中)而不是with ... end语法。但是,这并不能真正解决问题。一些experimantations之后,我觉得你并不需要在FSI文件以应用属性:

// 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 

这应该做的伎俩 - 可惜的是,我不知道是否有使用自动生成的结构方式同时隐瞒歧视工会的实施。

编辑看起来你可以指定识别联合的情况下在FSI文件,但它们标记为private,所以他们不会在模块的外部可见。所以也许这也会起作用:

// 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

太棒了!添加[]并删除其他属性可解决问题。我曾尝试与他们一起玩,但显然从来没有选择正确的组合。需要添加Sealed看起来像是一个bug(或者至少是一个不幸的不一致)。联合会自动密封(或者编译器说如果我也在FS文件中添加Sealed)。 – petebu 2011-06-05 20:32:20

+0

@petebu - 'Sealed'属性是故意的(编译器只是希望你在F#接口文件中明确地声明这个事实 - 尽管当接口文件包含声明类型时不需要)。 – 2011-06-05 20:48:22