Hatena::Grouphaskell

lnzntのHaskell日記 このページをアンテナに追加 RSSフィード

2014年11月24日(月)

Haskell で 初めての FizzBuzz

| 11:07 |  Haskell で 初めての FizzBuzz - lnzntのHaskell日記 を含むブックマーク はてなブックマーク -  Haskell で 初めての FizzBuzz - lnzntのHaskell日記  Haskell で 初めての FizzBuzz - lnzntのHaskell日記 のブックマークコメント

基本構文もわかったし、そろそろ FizzBuzz が書けるのでは、と書いてみた。

fizzBuzz :: [Int] -> [String]

fizzBuzz ns = map fizzBuzz' ns
              where
                fizzBuzz' n
                    | n `mod` 15 == 0 = "FizzBuzz"
                    | n `mod`  3 == 0 = "Fizz"
                    | n `mod`  5 == 0 = "Buzz"
                    | otherwise       = show n

main = do
    print $ fizzBuzz [1..100]

ここで fizzBuzz ns の ns が不要であることに気付いたので削る。

fizzBuzz :: [Int] -> [String]

fizzBuzz = map fizzBuzz'
           where
             fizzBuzz' n
                 | n `mod` 15 == 0 = "FizzBuzz"
                 | n `mod`  3 == 0 = "Fizz"
                 | n `mod`  5 == 0 = "Buzz"
                 | otherwise       = show n

main = do
    print $ fizzBuzz [1..100]

参考書籍によると、このように関数を関数で定義するのを「ポイントフリースタイル」というらしい。ここでいう「ポイント」は「.」でなく「圏論(数学の一分野:category theory)」の用語で Haskell でいう値のことらしい。(???まったくわからない。。。)

しげしげ、見ていると fizzBuzz' がうざい。本来こっちが主役の関数で map はその頭を修飾しているだけのようなので書き直す。(自分の考えが手続き的なので「map する」に囚われすぎた?)

fizzBuzz :: Int -> String

fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
           | n `mod`  3 == 0 = "Fizz"
           | n `mod`  5 == 0 = "Buzz"
           | otherwise       = show n

main = do
    print $ map fizzBuzz [1..100]

こっちのがいい気がする。

「map fizzBuzz」を一関数にまとめたければ、

fizzBuzzMap = map fizzBuzz
    :
    print $ fizzBuzzMap [1..100]

とすればいい。

対比の Ruby版。

#!/usr/bin/env ruby
# -*- coding: UTF-8 -*-

fizzBuzz = -> n do
              n % 15 == 0 ? "FizzBuzz" :
              n %  3 == 0 ? "Fizz"     :
              n %  5 == 0 ? "Buzz"     :
                            "#{n}"
           end

p (1..100).map &fizzBuzz

「map &fizzBuzz」をまとめるにはメソッド等を定義する。以下ではラムダを使う。

fizzBuzzMap = -> ns { ns.map &fizzBuzz }

p fizzBuzzMap.(1..100)