4

F# タプルの拡張メソッドを作成することはできますか? たとえば、インスタンス メソッド .Item1 および .Item2 (System.Tuple など) を追加するには、2 タプルに対して fst および snd を呼び出すのと同等ですか?

4

5 に答える 5

5

F# で (2 要素のSystem.Tuple<'T1, 'T2>) タプルを内部的に表す型には、実際には既にプロパティItem1Item2がありますが、これらは F# コンパイラによって隠されています。拡張メンバーをタプルに追加する明白な方法ではうまくいかないので、これがうまくいくとは思いません (しかし、私が知らない回避策があるかもしれません)。

Item1一般に、パターン マッチングは などのメンバーよりも好ましいと思いますItem2(また、C# 3.0 プログラマーは、タプルを操作するときにパターン マッチングのサポートを求めることがよくあります :-))。

その理由は、パターン マッチングでは名前を付ける必要があるからです。次の 2 つのコード スニペットを比較します。

let (width, height) = tuple
width * height

およびプロパティを使用するバージョン:

tuple.Item1 * tuple.Item2

2 番目は少し短いですが、明らかに読みにくくなっています。

于 2013-01-02T00:04:06.047 に答える
2

完璧ではありませんが、私はこれを使用しています。( http://www.fssnip.net/6Vから元のコードを借りて、小さな変更を加えました。)

[<AutoOpen>]
module TupleExtensions =
  type System.Tuple with
    static member Item1(t) = let (x,_) = t in x
    static member Item1(t) = let (x,_,_) = t in x
    static member Item1(t) = let (x,_,_,_) = t in x
    static member Item1(t) = let (x,_,_,_,_) = t in x
    static member Item1(t) = let (x,_,_,_,_,_) = t in x
    static member Item1(t) = let (x,_,_,_,_,_,_) = t in x

    static member Item2(t) = let (_,x) = t in x
    static member Item2(t) = let (_,x,_) = t in x
    static member Item2(t) = let (_,x,_,_) = t in x
    static member Item2(t) = let (_,x,_,_,_) = t in x
    static member Item2(t) = let (_,x,_,_,_,_) = t in x
    static member Item2(t) = let (_,x,_,_,_,_,_) = t in x

    static member Item3(t) = let (_,_,x) = t in x
    static member Item3(t) = let (_,_,x,_) = t in x
    static member Item3(t) = let (_,_,x,_,_) = t in x
    static member Item3(t) = let (_,_,x,_,_,_) = t in x
    static member Item3(t) = let (_,_,x,_,_,_,_) = t in x

    static member Item4(t) = let (_,_,_,x) = t in x
    static member Item4(t) = let (_,_,_,x,_) = t in x
    static member Item4(t) = let (_,_,_,x,_,_) = t in x
    static member Item4(t) = let (_,_,_,x,_,_,_) = t in x

    static member Item5(t) = let (_,_,_,_,x) = t in x
    static member Item5(t) = let (_,_,_,_,x,_) = t in x
    static member Item5(t) = let (_,_,_,_,x,_,_) = t in x

    static member Item6(t) = let (_,_,_,_,_,x) = t in x
    static member Item6(t) = let (_,_,_,_,_,x,_) = t in x

    static member Item7(t) = let (_,_,_,_,_,_,x) = t in x  

それの使い方:

let t = (1, 2, 3)
let item1 = Tuple.Item1(t)

ここで定義されている Tuple.Item1 は、fst よりも優れています。項目数に対して多態的です。これらの拡張メソッドを使用して n タプルを使用する関数を作成すると、関数本体を変更せずに n+1 タプルに拡張できます。代わりに、引数の型宣言を変更する必要があります。それはより楽です。

于 2016-09-15T02:18:18.843 に答える
0

fstおよび関数を使用してsnd、必要な値を取得することもできます (実際に必要な場合は、明らかに 3 番目、4 番目などに独自の値を記述します)。

于 2013-01-02T09:10:27.853 に答える
0

あなたが求めているのは、あまり機能的な方法ではないと思います。インスタンス メソッドを使用して独自の型を作成できますが、同時に、パターン マッチングなど、関数型プログラミングの多くの側面が失われます。

それ以外は、DU が適しているようです。

type MyTuple<'T, 'U> =
    | MyTuple of 'T * 'U
    with
    member this.MyItem1 = match this with | MyTuple(x,y) -> x
    member this.MyItem2 = match this with | MyTuple(x,y) -> y

let x = MyTuple(42, "foo")
let y1 = x.MyItem1    // 42
let y2 = x.MyItem2    // "foo"

@Tomas Petricek が指摘したように、プロパティItem1に名前を付けることはできません。Item2それらは既に に存在するためSystem.Tuple<'T1, 'T2>です。これを行おうとすると、エラーが発生します。

エラー FS2014: バイナリ [ファイル名] の書き込みで問題が発生しました: 型 [...] の pass2 でエラーが発生しました。エラー: 型 MyTuple`2 の pass2 でエラーが発生しました。エラー: プロパティ テーブルにエントリ 'Item1' が重複しています

于 2013-01-02T00:14:01.403 に答える