Search code examples
f#fizzbuzzactive-pattern

FizzBuzz with Active Patterns


I'm trying to understand Active Patterns, so I'm playing around with FizzBuzz:

let (|Fizz|_|) i = if i % 3 = 0 then Some Fizz else None
let (|Buzz|_|) i = if i % 5 = 0 then Some Buzz else None
let (|FizzBuzz|_|) i = if i % 5 = 0 && i % 3 = 0 then Some FizzBuzz else None

let findMatch = function
    | Some Fizz -> "Fizz"
    | Some Buzz -> "Buzz"
    | Some FizzBuzz -> "FizzBuzz"
    | _ -> ""

let fizzBuzz = seq {for i in 0 .. 100 -> Some i}
                |> Seq.map (fun i -> i, findMatch i)

Is this basically the right approach, or is there a better way to use Active Patterns here? Shouldn't I be able to make findMatch take an int instead of int option?


Solution

  • Your findMatch function should be:

    let findMatch = function
        | FizzBuzz -> "FizzBuzz" (* should be first, as pad pointed out *)
        | Fizz -> "Fizz"
        | Buzz -> "Buzz"
        | _ -> ""
    

    You can rewrite the last few lines:

    let fizzBuzz = Seq.init 100 (fun i -> i, findMatch i)
    

    Your active patterns are fine. One alternative is to use a complete active pattern:

    let (|Fizz|Buzz|FizzBuzz|Num|) i = 
        match i % 3, i % 5 with
        | 0, 0 -> FizzBuzz
        | 0, _ -> Fizz
        | _, 0 -> Buzz
        | _ -> Num i