2011-06-05 97 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