Generalized FizzBuzz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{-# LANGUAGE RankNTypes #-}
import Control.Applicative ((<|>))

type FizzBuzz = forall a . (Integral a, Show a) => a -> String

mkFizzBuzz :: (forall a . (Integral a, Show a) => [(a, String)]) -> FizzBuzz
mkFizzBuzz l n = if null fizzed then show n else fizzed
  where
    fizzed = mconcat (map fun l) n
    fun (d, s) x
        | x `mod` d == 0 = s
        | otherwise = mempty

standard :: FizzBuzz
standard = mkFizzBuzz [(3, "Fizz"), (5, "Buzz")]

custom :: FizzBuzz
custom = mkFizzBuzz [(3, "Fizz"), (5, "Buzz"), (7, "Xyzzy"), (13, "Quux")]

main :: IO ()
main = do
    putStrLn "Standard:"
    mapM_ (putStrLn . standard) [1..100]
    putStrLn "Custom:"
    mapM_ (putStrLn . custom) [1..100]