2011-01-02 16 views
0

この回答はStackOverflow(およびその他のソース)で検索されていますが、何も見つかりませんでした。私はウィジェット定義を持っていた場合のC#で F#リスト、IEnumberableなどの拡張メソッド

、言う:

class widget 
{ 
    public string PrettyName() { ... do stuff here } 
} 

と私はウィジェットのリストを簡単に印刷を可能にしたかった、私はこれを行う可能性があります:

namespace ExtensionMethods 
{ 
    public static PrintAll(this IEnumerable<Widget> widgets, TextWriter writer) 
    { 
     foreach(var w in widgets) { writer.WriteLine(w.PrettyName()) } 
    } 
} 

方法私はレコードタイプとコレクション(F#で好きなListやSeq)と同様のことを達成しますか?私はWidgestのリストを持っていて、このようなことをしたコレクションの関数を呼び出せるようにしたいと思います。関数がそれが付いているコレクションの状態を変更せず、新しい値を返すと仮定します(F#以降)。

答えて

4

F#ではまったく同じような解決策はありません。 F#拡張メンバーは、元のタイプのメンバーであるかのようにしか定義できないため、IEnumerable<Widget>などの特定のインスタンス化ではなく、汎用タイプIEnumerable<'T>でF#拡張を定義することができます。

C#では、より柔軟なコーディングスタイル(例:myWidgets.PrintAll(tw))を提供するために、拡張メソッドがよく使用されます。 F#では、通常、let-bound関数を定義し、パイプライン演算子を使用して同様の効果を得ます。例:

module Widget = 
    let printAll (tw:TextWriter) s = 
    for (w:Widget) in s do 
     writer.WriteLine(w.PrettyName()) 

open Widget 
let widgets = // generate a sequence of widgets somehow 
let tw = TextWriter() 
widgets |> printAll tw 
+0

上記のシナリオで使用するためにprintAll関数をウィジェットレコードタイプのメンバーとして定義するにはどうすればよいですか? – fbl

+0

@ flevine100 - 通常、printAllを型のメンバーとして定義するのではなく、モジュール内のレットバインド関数として定義します。私は例を含めるために私の答えを編集しました。 – kvb

+0

ありがとう! - 機能プログラミングは、明らかにコード構成について考えている別の方法です。 – fbl