26

しばらくの間、F#のオンとオフを切り替えようとしていましたが、延期され続けています。なんで?

どの「初心者」リソースを見ようとしても、演算子を使い始める非常に単純な例が表示されます->

しかし、この演算子が何を意味するのかを明確に簡単に説明できるものはまだどこにも見つかりませんでした。初心者でも説明が不要なほど明白なはずです。

したがって、私は本当に密集している必要があります。そうでない場合は、30年近く前の経験が私を妨げているのかもしれません。

誰かがそれを説明したり、それを説明する本当にアクセス可能なリソースを指摘したりできますか?

4

9 に答える 9

50

「->」は演算子ではありません。これは F# 構文の多くの場所に現れ、その意味は、より大きな構造の一部としてどのように使用されるかによって異なります。

型の中では、'->' は関数型を記述します。例えば

let f : int -> int = ...

「f」はintを取り、intを返す関数であると言います。

ラムダ (「fun」キーワードで始まるもの) 内では、「->」は引数を本体から分離する構文です。例えば

fun x y -> x + y + 1

指定された実装で 2 つの引数関数を定義する式です。

「一致」構文内の「->」は、パターンが一致した場合に実行されるコードからパターンを分離する構文です。たとえば、

match someList with
| [] -> 0
| h::t -> 1

各 '->' の左側のものはパターンであり、右側のものは左側のパターンが一致した場合に何が起こるかです。

理解の難しさは、「->」が単一の意味を持つ「演算子」であるという誤った仮定に根ざしている可能性があります。類推は「。」かもしれません。これまでコードを見たことがない場合は、C# で "." を分析してみてください。"obj.Method" と "3.14" と "System.Collections" を見ると、シンボルが異なるコンテキストで異なる意味を持つため、非常に混乱する可能性があります。ただし、これらのコンテキストを認識できる言語を十分に理解すると、物事が明確になります。

于 2008-09-19T20:56:26.237 に答える
13

基本的には「マップ先」を意味します。そのように、または「に変換される」またはそのようなものとしてそれを読んでください。

つまり、F#の20分のチュートリアルから

> List.map (fun x -> x % 2 = 0) [1 .. 10];;
val it : bool list
= [false; true; false; true; false; true; false; true; false; true]

コード(fun i-> i%2 = 0)は、ラムダ式と呼ばれる無名関数を定義します。この無名関数はパラメーターxを持ち、関数は「x%2 = 0」の結果を返します。これは、xが平。

于 2008-09-19T19:21:05.173 に答える
9

最初の質問-C#のラムダ式に精通していますか?もしそうなら、F#の->はC#の=>と同じです(私はあなたがそれを読んだと思います'は'に行きます)。

->演算子は、パターンマッチングのコンテキストでも見つけることができます

match x with
| 1 -> dosomething
| _ -> dosomethingelse

これがラムダ式なのか、それとも他の何かなのかはわかりませんが、「goesto」はまだ当てはまると思います。

たぶん、あなたが本当に言及しているのは、F#パーサーの「不可解な」応答です。

> let add a b = a + b
val add: int -> int -> int

これは、(ほとんどの例で説明されているように)addが2つのintを取り、intを返す「val」であることを意味します。私にとって、これはそもそも完全に不透明でした。つまり、addが1つのintを取り、2つのintを返すvalではないことをどうやって知ることができますか?

そうですね、ある意味ではそうです。addにintを1つだけ与えると、(int-> int)が返されます。

> let inc = add 1
val inc: int -> int

これ(カリー化)は、私にとってF#をとてもセクシーにするものの1つです。

F#に関する役立つ情報については、ブログが公式の「ドキュメント」よりもはるかに役立つことがわかりました。ここにチェックアウトする名前がいくつかあります。

于 2008-09-19T20:29:10.110 に答える
4

(a -> b) は「a から b への関数」を意味します。型注釈では、関数型を示します。たとえば、 f : (int -> String) は、f が整数を取り、文字列を返す関数を参照することを意味します。次のように、そのような値のコンストラクターとしても使用されます。

val f : (int -> int) = fun n -> n * 2

これは、ある数 n からその同じ数に 2 を掛けた値への関数である値を作成します。

于 2008-09-19T19:24:39.297 に答える
1

Microsoftから:

関数型は、ファーストクラスの関数値に与えられる型であり、int->intと記述されます。名前が付けられていないことを除けば、.NETデリゲートタイプに似ています。すべてのF#関数識別子はファーストクラスの関数値として使用でき、無名関数の値は(fun ...-> ...)式の形式を使用して作成できます。

于 2008-09-19T19:22:50.177 に答える
1

この質問に対する多くの素晴らしい回答、ありがとう。物事をまとめる編集可能な回答をここに入れたいと思います。

C# の理解に精通している場合、-> => ラムバ式と同じであることは、最初のステップとして適切です。この使用法は次のとおりです:-

fun x y -> x + y + 1

次と同等として理解できます:-

(x, y) => x + y + 1;

ただし、 -> には、上記のような 2 つのパラメーターを取る関数を (正しい用語ですか?) 1 つのパラメーターのみを取る一連の関数に減らすことができるという概念に由来する、より基本的な意味があることは明らかです。

したがって、上記を次のように説明すると:-

Int -> Int -> Int

-> が正しい連想であることを知って本当に助かりました。したがって、上記を考慮することができます:-

Int -> (Int -> Int)

あはは!Int を受け取って (Int -> Int) を返す関数があります (カリー化された関数?)。

-> も型定義の一部として現れる可能性があるという説明も役に立ちました。(Int -> Int) は、Int を受け取り、Int を返す関数の型です。

-> はマッチングなどの他の構文にも表示されますが、同じ意味はありませんか? あれは正しいですか?よくわかりません。同じ意味だと思いますが、私はまだそれを表現する語彙を持っていません。

この回答の目的は、さらなる回答を生み出すことではなく、より決定的な回答を作成するために、人々が共同で編集することであることに注意してください。最終的には、すべての不確実性と綿密な部分 (この段落など) を削除し、より良い例を追加することをお勧めします。この回答を、できるだけ初心者がアクセスできるようにしておきましょう。

于 2008-09-20T21:15:45.137 に答える
1

関数を定義するコンテキストでは=>、C# 3.0 のラムダ式に似ています。

F#: let f = fun x -> x*x
C#: Func<int, int> f = x => x * x;

F#の->はパターン マッチングでも使用されます。つまり、式が と の間の部分|と一致する場合->、その後に続くもの->が結果として返されます。

let isOne x = match x with
 | 1 -> true
 | _ -> false
于 2008-09-19T20:15:18.927 に答える
1

ここにはすでに素晴らしい答えがたくさんありますが、それについての別の考え方を会話に追加したいだけです.

' -> ' は関数を意味します。

'a -> 'b は、'a を受け取って 'b を返す関数です。

('a * 'b) -> ('c * 'd) は、型 ('a, 'b) のタプルを取り、('c, 'd) のタプルを返す関数です。int/string などは float/char を返します。

興味深いのは、'a -> 'b -> 'c のカスケードの場合です。これは、'a を取って関数 ('b -> 'c) を返す関数、または 'b -> 'c を取る関数です。

したがって、次のように書くと: let fxyz = ()

型は f : 'a -> 'b -> 'c -> unit になるため、最初のパラメーターのみを適用すると、結果はカリー化された関数 'b -> 'c -> 'unit になります。

于 2008-09-19T19:58:04.443 に答える
0

Haskell などの言語の優れた点 (F# では非常に似ていますが、正確な構文はわかりません。これは理解に役立つはずです -> ですが)、引数の一部のみを適用して、カリー化された機能:

adder n x y = n + x + y

言い換えれば、「私に3つのものをください。それらを足し合わせます」. 数値を投げると、コンパイラは nx と y の型を推測します。あなたが書くと言う

adder 1 2 3

1、2、3 の型は Int です。したがって:

adder :: Int -> Int -> Int -> Int

つまり、3 つの整数を与えてください。最終的には整数になります。または、次のように言っているのと同じです。

five :: Int
five = 5

しかし、ここがいいところです!これを試して:

add5 = adder 5

ご存じのとおり、adder は int、int、int を受け取り、int を返します。ただし、すぐにわかるように、それは完全な真実ではありません。実際、add5 は次のタイプになります。

add5 :: Int -> Int -> Int

整数 (一番左) を「はがし」、関数に直接貼り付けたかのようになります。関数シグネチャをよく見てみると、 -> が右結合であることがわかります。

addder :: Int -> (Int -> (Int -> Int))

これにより、非常に明確になるはずです: adder に最初の整数を与えると、最初の矢印の右側にあるものに評価されます。または:

add5andtwomore :: Int -> (Int -> Int)
add5andtwomore = adder 5

「adder 5」の代わりに add5andtwomore を使用できるようになりました。このようにして、別の整数を適用して (たとえば) "add5and7andonemore" を取得できます。

add5and7andonemore :: Int -> Int
add5and7andonemore = adder 5 7

ご覧のとおり、add5and7andonemore はまったく別の引数を必要としており、それを与えると突然整数になります!

  > add5and7andonemore 9
 => ((add5andtwomore) 7) 9
 => ((adder 5) 7) 9)
<=> adder 5 7 9

(5 7 9) を加算器 (nxy) にパラメータを代入すると、次のようになります。

  > adder 5 7 9 = 5 + 7 + 9
 => 5 + 7 + 9
 => 21

実際、plus は int を取り、別の int を返す単なる関数でもあるため、上記は実際には次のようになります。

  > 5 + 7 + 9
 => (+ 5 (+ 7 9))
 => (+ 5 16)
 => 21

ほら!

于 2008-09-19T19:45:11.090 に答える