1

私はF#とアクティブなパターンにかなり慣れていないので、説明できない異常に遭遇しました。

module Eval =
let (|Bet|Pass|) (test:BetChoice) =
    match test with
        | BetChoice.Bet -> Bet
        | BetChoice.Pass -> Pass

let (|NoBet|Bet|Pass|) (test:Nullable<BetChoice>) : Choice<unit, unit, unit> =
    match test.HasValue with
        | true -> match test.Value with 
                      | BetChoice.Bet -> Bet
                      | BetChoice.Pass -> Pass
        | false -> NoBet

let FlipByWinner ((value:int), (awins:bool)) =
    match awins with
    | true -> (value, -value)
    | false -> (-value, value)

let Evaluation (awins:bool) (player11:BetChoice) (player21:BetChoice) (player12:Nullable<BetChoice>) =
     match player11 with
     | Pass -> match player21 with
               | Pass -> FlipByWinner(1, awins)
               | Bet-> match player12 with
                       | Bet -> FlipByWinner(2, awins)
                       | Pass -> FlipByWinner(1, false)
                       | NoBet -> raise (System.ArgumentException("invalid strategy"))
     | Bet ->  match player21 with
               | Bet -> FlipByWinner (2, awins)
               | Pass -> FlipByWinner (1, false)

これはコンパイルされません。微調整を加えるだけで意図したとおりに機能させることができますが、何が起こっているのか正確にわからないため、少し緊張します...2番目のパターンの名前を「(| NoBet | Bet1 | Pass1 | )」と関連するパターンがコード全体で変更された場合、それは機能しますが、これに型の不一致の例外がある理由はわかりません。

また、ほとんど同じであるが完全ではない2つのアクティブなパターンを処理する良い方法はありますか?一般的なものを一緒に因数分解する方法があるはずのようです。(補足として、コピー/貼り付けでインデントが台無しになっているように見えます。これはすべてモジュールEvalの一部です)。

4

1 に答える 1

3

はい、最初の問題は完全に理にかなっています。同じ名前空間に同じ名前の 2 つのアクティブなパターン タグを含めることはできません。これは、F# コンパイラが実際にアクティブなパターン名を生成する方法に関係しています。リフレクターを見ると、生成されたコードは次のとおりです。

type Alpha = Foo | Bar
let (|Foo|Bar|) = ...

概念的にアクティブなパターンと識別された共用体は非常に似た概念ですが、非常に異なります。

とにかく、あなたが求めている問題は、大部分が似ている/異なっているアクティブなパターンのセットが 2 つある場合にどうするかということです。私がお勧めしたいのは、部分的なアクティブ パターンを使用することです。このブログ投稿を参照してください。

例では、次のようなものが必要なようです。

let (|IsBet|_|) = ...
let (|IsPass|_|) = ...

そうすれば、プレイヤー 11 とプレイヤー 21 の両方に対して同時にパターン マッチを行うことができます。

match player11, player21 with
| IsPass & IsPass -> ...
| IsPass & IsBet  -> ...
| IsBet  & IsPass -> ...
| IsBet  & IsBet  -> ...

これは、コードのクリーンアップに大いに役立つはずです。

于 2010-09-08T22:50:09.510 に答える