FizzBuzz一般化

http://karetta.jp/article/blog/oneline/030146より。

$ runhaskell FizzBuzz3.hs 1 100 2 Hage 3 Fizz 5 Buzz
module Main where

import System (getArgs)

data FB a = FB (a, String)

instance Monad FB where
  return x = FB (x, "") 
  m >>= f  = bind m f 
    where bind (FB (x, y)) f = let FB (m, n) = f x in FB (m, y ++ n)

instance (Show a) => Show (FB a) where
  show (FB (x, "")) = show x
  show (FB (_, y))  = y 

main = do
    (x:y:xs) <- getArgs
    f <- return $ fizzbuzz xs
    mapM_ (print . f) [read x..read y]

fizzbuzz :: [String] -> Int -> FB Int 
fizzbuzz [] n = return n
fizzbuzz (x:y:xs) n = (f x y n) >>= fizzbuzz xs
  where f x y n | n `mod` (read x) == 0 = FB (n, y)
                | otherwise = return n