11

次のコードをコンパイルしようとすると、エラーが発生することに気付きました。

let xx =
  seq {
    let! i = [ 1; 2 ]
    let! j = [ 3; 4 ]
    yield (i,j)
  }

これが与えるエラーは、「error FS0795: The use of 'let! x = coll' in sequence Expressions is no longer allowed. Use 'for x in coll' instead.」です。このメッセージはもちろん明確で、修正方法を示しています。固定コードは次のようになります。

let xx =
  seq {
    for i in [ 1; 2 ] do
      for j in [ 3; 4 ] do
        yield (i,j)
  }

私の質問は、これを修正する方法ではなく、なぜ「させてください!」そもそもシーケンス式で許可されていませんか? 私はどのようにすることができるという事実を見ることができます!式を繰り返し処理することに驚く人もいるかもしれませんが、それだけでこの構造が許可されないわけではありません。また、"let!" を含むバージョンのように、ここでは "for" がより強力であることがわかります。「シーケンス式の最後まで」として反復の範囲で焼き付けます。

ただし、コードをインデントせずにシーケンスを反復できることは、まさに私が探していたものでした (ツリー構造をトラバースするため)。このセマンティックを取得するには、「seq」式ビルダーとほとんど同じように機能する新しい式ビルダーを作成する必要があると思いますが、「let!」を許可します。反復のためですね。


以下のブライアンのコメントに基づいて追加され、私の根本的な問題の解決策を提供します。

forブロックのインデントが不要であることを認識していませんでした。2 番目のサンプルは次のように書き直すことができます。

let xx =
  seq {
    for i in [ 1; 2 ] do
    for j in [ 3; 4 ] do
    yield (i,j)
  }

...ツリー構造をトラバースするときに増え続けるインデントを取り除きます。この構文では、次のように、追加のインデントを必要とせずにforステートメントの間に追加のステートメントを使用することもできます。

let yy =
  seq {
    for i in [ 1; 2 ] do
    let i42 = i+42
    for j in [ 3; 4 ] do
    yield (i42,j)
  }

さて、これらのステートメントにインデントが必要だと思った理由を理解できれば...

4

1 に答える 1

8

ほんの数週間前、私は Don Syme と共に、F# 計算式 (シーケンス式、非同期ワークフローなど) の構文選択の背後にある動機のいくつかを説明しようとする論文を書きました。ここで見つけることができます。あなたの質問に明確な答えを与えるものではありませんが、役立つかもしれません。

一般に、何らかのタイプがM<'T>あり、計算ビルダーを定義している場合は、メソッドを追加Forして、構文Bindを有効にすることができます。forlet!

For  : seq<'T> -> ('T -> M<'T>) -> M<'T>
Bind : M<'T>   -> ('T -> M<'T>) -> M<'T>

への入力Forは常に何らかの sequenceseq<'T>である必要がありますが、 への入力は定義するBindタイプM<'T>である必要があります。

シーケンス式では、これら 2 つの操作は同じ型を持つため、同じことを行う必要があります。シーケンス式は両方を提供できますが、1 つのことに対して 2 つの異なるキーワードを使用すると混乱するため、おそらく 1 つだけを許可することをお勧めします。一般的な原則は、comp { .. }ブロック内のコードは通常のコードのように動作する必要があるということです。またfor、通常の F# コードに存在するため、seq<'T>.

于 2012-04-18T10:20:50.607 に答える