2016-01-24 2 views
7

私はF#にMAPがあることを知っていますが、.NET辞書を使用したいと考えています。今.NETでの変更可能な辞書<T, T> FでStructuralComparisonとEqualityを使用する方法

type ExprC = 
    | StrC of string 
    | BoolC of bool 
    | IntC of int32 
    | DecC of decimal 
    | ArrayC of int * array<ExprC> 
    | RelC of RelationC 
and RelationC = Dictionary<string, ExprC>   

は、私が解決したい問題は構造的平等とRelationCの種類を提供する方法である:この辞書は、すなわちF#の値+ dictのように文字列としてキーと値を、持っています。実際のストレージをカプセル化する必要がある場合、ディクショナリの代わりとなるコンテナを作成する方法、変更可能な操作に使用する方法、構造的に同等であるかどうか現在の答えを


、このコードは動作しない(呪いの実装では、しかし、これはコンパイルすらない、完全なものではありません):

[<CustomEquality; CustomComparison>] 
type MyDict() = 
    inherit Dictionary<string, ExprC>() 
    override this.Equals x = 
     match x with 
     | :? MyDict as y -> (this = y) 
     | _ -> false 

    override this.GetHashCode() = 
     hash this 

    interface System.IComparable with 
     member x.CompareTo yobj = 
      match yobj with 
      | :? MyDict as y -> compare x y 
      | _ -> invalidArg "MyDict" "cannot compare values of different types" 

and [<StructuralEquality;StructuralComparison>] ExprC = 
    | IntC of int 
    | StrC of string 
    | MapC of MyDict 

これはエラーです:

Error FS0377: This type uses an invalid mix of the attributes 'NoEquality', 'ReferenceEquality', 'StructuralEquality', 'NoComparison' and 'StructuralComparison' (FS0377)

+2

好奇心で、 'Map'ではなく' Dictionary'でこれをしたいと思う特別な理由がありますか? – TheInnerLight

+0

パフォーマンス。 .NETディクテーションは高速です(https://stackoverflow.com/questions/3396196/f-fsharpmap-vs-dictionary-performance)。私の使用事例では、私はそれをたくさん必要とします。プラス、好奇心。良い市民を.NETクラスに変換する方法を知っておくと便利だと思います) – mamcx

+2

あなたはプロファイルを作成してパフォーマンスの問題を見つけましたか、それとも将来に問題があると思いますか?それが問題なのかどうか分からなければ、あなたの人生を困難にしないでください。それを明白な方法で行い、必要に応じて後で問題を解決してください。 – TheInnerLight

答えて

2

にはを使用する必要があります。Dictionary<string, ExprC>を使用する場合は、Dictionary<'k, 'v>から派生し、Equals

type MyDict() = 
    inherit Dictionary<string, ExprC>() 
    override this.Equals x = 
     true // real implementation goes here 
    override this.GetHashCode() = 
     0 // real implementation goes here 

ここでは、構造的な平等を持っているEqualsを実装する必要があるだろう、とあなたはあなたEquals実装を一致させるためにGetHashCodeを実装する必要があります。

具体的なクラスDictionary<'k, 'v>が不要な場合は、IDictionary<TKey, TValue>を実装する独自のクラスを定義することもできます。

これは可能な限り多くの作業のようです。このタイプは、無効なミックスを使用しています」理由は何ですか:更新されたオリジナルのポストの終わりの質問について

let m1 = Map.ofList [("foo", 1); ("bar", 2); ("baz", 3)] 
let m2 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 3)] 
let m3 = Map.ofList [("bar", 2); ("foo", 1); ("baz", 4)] 

> m1 = m2;; 
val it : bool = true 
> m1 = m3;; 
val it : bool = false 
+0

さらに、 'Map'への変更可能な参照を保持する構造体を定義することもできます。平等の計算は本当に簡単になります。 – CaringDev

+0

これはどのように構造体で行うのですか? – mamcx

+0

値型から派生することはできません。 –

1

:デフォルトでは構造的平等を持っているMapを使用する方がはるかに簡単になるだろう。 .. "?これは、F#コンパイラのバグです。エラーメッセージは誤解を招く恐れがあります。see Github解決策は、単にすべての属性をMyDictから削除することです。

関連する問題