2012-04-18 7 views
11

私はあなたがそれをコンパイルしようとすると、次のコードは、エラーを与えることに気づい:なぜseq計算ビルダーは "let!"を許可しないのですか?

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

これが与えるエラーは「エラーFS0795です:シーケンス式で 『!聞かせて、X =蔵』の使用はnoですもっと長い間使用できます。代わりに 'for coll in x'を使用してください。 "このメッセージは当然のことであり、修正方法を示しています。固定コードは次のようになります。

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

私の質問は、この問題を解決する方法ではありませんが、なぜ "let!"最初のシーケンス式では許可されていませんか?私はどのようにして事実を見ることができます!表現を繰り返すことは、いくつかの人には驚きになるかもしれませんが、それは構造を許さないほど十分ではありません。私はまた、 "for"のバージョンとして、 "for"がより強力であることも見ています。反復の範囲を「シーケンス式の終わりまで」とします。

しかし、コードをインデントすることなくシーケンスを繰り返し処理できることは、私が探していたもの(ツリー構造をトラバースするためのもの)でした。私はこのセマンティックを得るために、 "seq"式ビルダーのように機能する新しい式ビルダーを作成しなければならないと考えていますが、 "let!"反復のために、そうではありませんか?


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

私は用ブロックにくぼみが必要とされていません実現しなかった、と第二のサンプルは次のように書き直すことができます。

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

...ツリー構造を横断するときに増加するインデントを取り除きます。構文は次のとおりであっても同様に、余分なインデントを必要とせずにため間の文で追加の文を許可します。私は、これらのステートメントは、インデントを必要とするだろうと思った理由だけで、私が把握できれば...、今

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

+4

非同期バインディングで 'let! 'と混乱する可能性があります。 –

+1

インデントのないものを試しましたか? – Brian

+0

@Brian「インデントのないものを試しましたか? - いや、何らかの理由で私は 'のためのインデントが必要ではないことを認識していませんでした。提案していただきありがとうございます!厳密に言えば、質問に答えることはできませんが、受け入れ可能な回避策を提供します。 –

答えて

8

ちょうど数週間前、私はDon Symeと書かれた論文を書いて、F#計算式(シーケンス式、非同期ワークフローなど)の構文選択の背後にある動機づけについて説明しようとしました。あなたはfind it hereすることができます。それはあなたの質問に明確な答えを与えませんが、それは助けるかもしれません。一般的に

、あなたには、いくつかのタイプM<'T>を持っていて、計算ビルダーを定義しているとき、あなたは方法ForBindforlet!構文を有効にするために追加することができます。

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

Forの入力は、常にいくつかをする必要がありますシーケンスseq<'T>Bindの入力は、定義するタイプM<'T>でなければなりません。

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

+1

説明をありがとう!個人的には、たとえ機能的に同じであっても、それらのそれぞれにつながる思考列が異なる可能性があるので、両方の構文オプションを残してしまったと思います。私のケースでは、BindシグネチャとM <'T>は、 'T'の何らかのコレクションを表すことができます。後で良い古いseq <'T>が私が必要なものすべてをすでに行ったことに気づいたので、seq {...}のBindを使用しようとしました。これは "let!" seq {...}式の内部にあります。それは私がエラーメッセージにぶつかったところでした... –

+2

いい紙、トマス! – Daniel

+1

現在の論文へのリンクは404ですが、それを見つける別の方法はありますか? – VisualMelon

関連する問題