Seq.groupBy と Seq.collect で FizzBuzz

思いつきで試してみたらできました。

一度、Seq.groupByで1から100までの数値をグループ分けし、その後でキーと値を入れ替えるような処理をSec.collectで行って、数値でソートして、文字でグループされていたかどうかをパターンマッチングでみて、最後に出力しています。

[<Test>]
let ``fizzbuzz with Seq.groupBy and Seq.collect``() =

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

seq { 1 .. 100 }
|> Seq.groupBy (function
| Fizz & Buzz -> Some("fizzbuzz")
| Fizz -> Some("fizz")
| Buzz -> Some("buzz")
| _ -> None)
|> Seq.collect (function key, value -> value |> Seq.map(fun n -> (n, key)))
|> Seq.sortBy (fst)
|> Seq.map (function
| _, Some(s) -> s
| n, None -> string(n))
|> Seq.iter (printfn "%s")

unit optionを返すアクティブパターンを作れることがわかりました。単に条件を判定したいだけの場合はこれでいいですね。