3

単純な関数を定義すると:

let myConcat a b = 
    a + "+" + b

次に、関数は F# のファーストクラスの値であるという主張を考えると、次のように使用できると予想されますmyConcat

let result = myConcat "a" (fun () -> "b")

文字列「a + b」を生成するのではなく、次のエラーが表示されます。

error FS0002: This function takes too many arguments, or is used in a context where a function is not expected

うまくいけば、私は単に構文が間違っているだけですが、F# では関数を値として真に使用できないように見えます。ここで何が起こっているのか誰か説明できますか?

編集 私が求めていることをさらに明確にするために、同等のC#コードを使用できます。

public string myConcat(string a, string b) { return a + "+" + b; }

ただし、パラメーター b で「call later function」を渡したい場合は、次のようにする必要があります。

public string myConcat(string a, Action<string> b) { return a + "+" + b(); }

または、次のように呼び出すこともできます。

Func<string> b = () => "b";
var result = myConcat("a", b());

C# は (私の知る限り)、関数が第一級の値であると主張していません。F# はそう主張します。unit -> string 関数を「遅延評価された」文字列値として扱うことができない場合の違いは何ですか?

4

3 に答える 3

6

作成しているラムダの型は (ユニット -> 文字列) です。次に、電話をかけようとしています。

文字列 -> 文字列 -> (単位 -> 文字列) -> 文字列

予想される呼び出しに型が必要な場合

文字列 -> 文字列 -> 文字列 -> 文字列

したがって、ラムダを渡そうとしていますが、実際に渡したいのはラムダを呼び出した結果です

let result = myConcat "a" ((fun() -> "b")())
于 2013-09-05T21:34:17.603 に答える
4

このように呼び出すだけで済みます。let result = myConcat "a" ((fun() -> "b")())

myConcat を作成すると、次のように解釈されます。val myConcat : a:string -> b:string -> string

2 番目の引数が文字列であることを期待しており、それをメソッドに渡しています。

必要なことを行うには、myConcat を次のように宣言する必要がありますlet myConcat a b = a + "+" + b()。その後、2 番目の引数として関数を渡すことができます。

これは、次のように解釈されます。val myConcat : a:string -> b:(unit -> string) -> string

于 2013-09-05T21:33:06.143 に答える
2

主に Mauricio Scheffer に感謝します。私の質問に対する答えがあります。

C# や他の多くの言語も、「関数はファースト クラスの値」を提供します。ただし、オブジェクト指向言語であるため、C# ではこれを通常「関数はファースト クラス オブジェクト」と表現します。「関数は第一級の値である」というフレーズは、単に値であるかのように、パラメーターを介して関数参照を別の関数に渡す機能を指します。たとえば、 unit -> string 値が単なる文字列値と同等であるという「魔法の」解釈はありません。単に、 unit -> string 関数が別の値に渡す有効な値であるということです。

F# の強力な型推論機能により、C# の場合のように F# で参照される関数の unit -> string 型を指定する必要はありませんが、コンパイラはこの型を推論するため、指定しません。匿名ユニットでラップせずに単純な文字列を渡すことができます->最初に文字列関数。

あなたが私よりもこのことをよく理解していて、私が何か間違っている場合は、編集して間違いを修正してください。

于 2013-09-12T20:51:39.583 に答える