2016-12-07 3 views
1

次の行はコンパイルされません:「関数」構文を使用してパターンマッチングを実行するときに値を取得するにはどうすればよいですか?

| IsNeither -> sprintf "%i" // ??? 

をここでは、この行が属する機能があります:

let run = function 

    | IsFizzBuzz -> "Fizz Buzz" 
    | IsFizz  -> "Fizz" 
    | IsBuzz  -> "Buzz" 
    | IsNeither -> sprintf "%i" // Doesn't compile 

ここでは、プログラム全体です: モジュールの温度

は、
let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function 
    | n when n % 3 = 0 && 
      n % 5 = 0 -> IsFizzBuzz 
    | n when n % 3 = 0 -> IsFizz 
    | n when n % 5 = 0 -> IsBuzz 
    | n ->    IsNeither 

let run = function 

    | IsFizzBuzz -> "Fizz Buzz" 
    | IsFizz  -> "Fizz" 
    | IsBuzz  -> "Buzz" 
    | IsNeither -> sprintf "%i" // Doesn't compile 

let result = [1..16] |> List.map(run) 

署名の "function"構文を使用して値を抽出することはできますか?

例:

let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function 

答えて

9

asキーワードを使用して、あなたのパターンを再定義する必要はありません解決策があります:

let run = function 
    | IsFizzBuzz -> "Fizz Buzz" 
    | IsFizz  -> "Fizz" 
    | IsBuzz  -> "Buzz" 
    | IsNeither as n -> sprintf "%i" n 

これうまくなど、判別共用体のケースにマッチする、アクティブパターン全体で動作します目立つユースケースはタイプチェックです。| :? string as s

7

最も簡単な解決策は、パターンの値部分を作ることであろう。

let (|IsFizz|IsBuzz|IsFizzBuzz|IsNeither|) = function 
    | n when n % 3 = 0 && 
      n % 5 = 0 -> IsFizzBuzz 
    | n when n % 3 = 0 -> IsFizz 
    | n when n % 5 = 0 -> IsBuzz 
    | n    -> IsNeither n 

let run = function 
    | IsFizzBuzz -> "Fizz Buzz" 
    | IsFizz  -> "Fizz" 
    | IsBuzz  -> "Buzz" 
    | IsNeither n -> sprintf "%i" n 
6

neitherの場合は、すべての値を「ドメイン」に分割できない可能性がありますので、おそらくPartial Active Patternがベットになります選択肢の選択。それは1でも一般IsDivisibleBy

に賛成したもの FizzBuzz機能を取り除くことができ、この道を行く

// common code extracted and inlined (optional) 
let inline isDivisibleBy divisor dividend = 
    if dividend % divisor = LanguagePrimitives.GenericZero 
    then Some() 
    else None 

let (|Fizz|_|) = isDivisibleBy 3 
let (|Buzz|_|) = isDivisibleBy 5 

let run = function Fizz & Buzz -> "FizzBuzz" 
       | Fizz  -> "Fizz" 
       | Buzz  -> "Buzz" 
       | x   -> string x 

let result = List.map run [1 .. 16] 

(いくつかの変更のコストで)コードを簡素化することができますAND pattern
関連

let inline (|IsDivisibleBy|_|) divisor dividend = 
    if dividend % divisor = LanguagePrimitives.GenericZero 
    then Some() 
    else None 

let run = function IsDivisibleBy 3 & IsDivisibleBy 5 -> "FizzBuzz" 
       | IsDivisibleBy 3     -> "Fizz" 
       | IsDivisibleBy 5     -> "Buzz" 
       | x         -> string x 

let result = List.map run [1 .. 16] 

、あるいはそのようにあなたはまだそれらのFizzをしたいとBuzzあなたはまだ

を行うことができれば
関連する問題