2012-02-09 14 views
2

なぜこれは機能しませんか?ファンクションシグネチャのF#パターンマッチング

type RetryBuilder(max) = 
    member x.Return(a) = a    // Enable 'return' 
    member x.Delay(f) = f    // Gets wrapped body and returns it (as it is) 
             // so that the body is passed to 'Run' 
    member x.Zero() = failwith "Zero" // Support if .. then 
    member x.Run(f) =     // Gets function created by 'Delay' 
    let rec loop 0 (Some(ex)) = raise ex 
    let rec loop n maybeEx = try f() with ex -> loop (n-1) (Some(ex)) 
    loop max None 

let retry = RetryBuilder(4) 

「この式に不完全なパターンが一致します。例えば、値 '1'は、パターン 'でカバーされていないケースを示すことができる。

しかし、なぜそれは以下のものと一致しませんか?私が正しく覚えていれば、ハスケルはそれにマッチします、なぜF#はありませんか?

答えて

5

あなたはHaskell構文でF#コードを書いています。あなたのコードをコンパイルする理由は、F#コンパイラは2つのloop関数があり、前者は後者が影を付けていると考えています。明らかに最初のloop関数では、最初のパラメータの場合は0、2番目のパラメータの場合はNone以外の整数でパターンマッチングが失敗します。近くにHaskellの構文に

宣言は次のようになります。

let rec loop = function 
    | 0, Some ex -> raise ex 
    | n, maybeEx -> try f() with ex -> loop (n-1, Some ex) 
loop(max, None) 
+0

興味深いです。素敵でコンパクトですが、f-nアプリケーションの代わりにw/tuplesを使用しています – Henrik

+0

私はまだ興味があります。なぜF#は上の仕事をすることができないのですか? – Henrik

+1

私はそれが歴史的な理由によるものだと思います。あなたの宣言は、OCaml/SMLでも動作しません。 Haskellとは異なり、OCaml/F#では、関数を宣言するために 'let(rec)'を使わなければなりません。あまりにも多くの 'let rec'は経済的でないようだ。 – pad

関連する問題