Haskellらしいfizzbuzz/OCamlらしいfizzbuzz

30分プログラム、その61。Haskellらしいfizzbuzz/OCamlらしいfizzbuzzを書いてみよう。

fizzbuzz :: [Int]->[String]
fizzbuzz = map f
    where f n | n `mod` 15 == 0 = "fizzbuzz"
              | n `mod` 3 == 0 = "fizz"
              | n `mod` 5 == 0 = "buzz"
              | otherwise = show n

fizzbuzzList :: [String]
fizzbuzzList = fizzbuzz [1..]

main = mapM_ putStrLn $ take 100 fizzbuzzList

Haskellらしいところ。

  • ポイントフリー
  • 型宣言をしている
  • ガード節を使っている
  • 無限リストを使っている
  • mapM_を使っている
let rec range n m = if n == m then [n] else n::(range (n+1) m);;

let fizzbuzz l =
  let f = 
    function 
	n when n mod 15 == 0 -> "fizzbuzz"
      | n when n mod 3 == 0 -> "fizz"
      | n when n mod 5 == 0 -> "buzz"
      | n -> string_of_int n
  in List.map f l;;

let _ = List.iter (Printf.printf "%s\n") (fizzbuzz (range 1 100));;

OCamlらしいところ

  • 再帰にはrecがいる
  • whenによるガード節。使い型を忘れてたのでぐぐったら自分の日記がでてきた
  • List.iterを使っている。副作用がない言語だったら、これ無意味でしょ?
  • Printf.printfを使っている。これ、型安全なんだぜ

あと、時間測定もしてみた。

言語 real user sys
Haskell(runghc,インタプリタ) 0m1.493s 0m1.185s 0m0.136s
Haskell(ghc,ネイティブコンパイラ) 0m0.052s 0m0.006s 0m0.015s
OCaml(ocaml,インタプリタ) 0m0.071s 0m0.037s 0m0.014s
OCaml(ocamlc,バイトコンパイラ) 0m0.014s 0m0.004s 0m0.006s
OCaml(ocamlopt,ネイティブコンパイラ) 0m0.016s 0m0.002s 0m0.008s

要するに、runghcは遅い。

これを両方つくって、5分程度あまった。