2

F# function is very different from normal CLR method because of currying support. For example function

let inc a = a + 1

Will have type Microsoft.FSharp.Core.FSharpFunc<int,int>. It creates problems with C# interoperability. Functions must be designed specially to be easily called from C#.

What is the rationale behind this design? I believe that the reason is currying support. But currying can be implemented using closures. For example this code:

let add a b = a + b
let inc = add 1

can be easily transformed into this by the compiler:

let add a b = a + b
let inc = fun x -> add 1 + x

both add and inc in this case can be normal System.Func objects. I believe that there is some interesting reasons behind this design decision.

4

3 に答える 3

10

私が覚えている限り、F#の関数に別のタイプを使用する動機は、パフォーマンスでした(以前のバージョンFSharpFunc<...>では実際にはと呼ばれていましたFastFunc<...>)。最近の開発については完全にはわかりませんが(F#チームがVisual Studio 2010でデリゲートが機能するかどうかを確認するためにいくつかのテストを行ったと確信しています)、問題をどのように理解したかを次に示します。

関数がある場合add : int -> int -> int、その関数はデリゲートとして表すことができますFunc<int, Func<int, int>>(カレー表現を使用)。問題は、のような両方のパラメータを使用して呼び出したい場合が非常に多いことですadd 1 2

ネストされたFunc型の表現を使用すると、これはにコンパイルされadd.Invoke(1).Invoke(2)ます。

ただし、のような関数をコンパイルする場合add、F#コンパイラは実際に新しいクラスを作成します。たとえば、このクラスは2つの引数AddClass継承FSharpFunc<int, FSharpFunc<int, int>> 2つの引数を使用して追加のInvokeオーバーロードを追加します。これは、ほとんどの場合、add 1 21回の呼び出しにコンパイルできることを意味しますadd.Invoke(1, 2)

この設計により、F#コードが高速になります。相互運用性は少し複雑になりますが、それほど多くはありません。デリゲートを受け取るF#メンバーまたは関数を作成するのはかなり簡単です。

let foo (inc : Func<int, int>) = inc.Invoke(41)

(タイプアノテーションを追加してから呼び出す必要がありますが、ファーストクラスの値としてf.Invoke使用して他の関数に渡すこともできます)f.Inokve

于 2013-02-08T13:51:25.720 に答える
1

私の推測では、F#表現は大きなステップのセマンティクスをサポートしていますが、サポートSystem.Funcしていません。

于 2013-02-10T18:02:15.670 に答える
1

C#と相互運用する最良の方法は、すべてをクラス/メンバーでラップすることです。C#は、メンバーの内部動作を確認する必要はありません。

于 2013-02-17T15:40:08.833 に答える