Hacker News new | ask | show | jobs
by wz1000 4069 days ago
Here's a version in Haskell that has the same functionality:

    fizzbuzz i triggers = map (\x -> fromMaybe (show x) $ 
                                               liftM mconcat (sequence triggers) x) 
                              [i..]

    fizzbuzz 1 $ [\i -> ["Fizz" | i `rem` 3 == 0]
                 ,\i -> ["Buzz" | i `rem` 5 == 0]
                 ]
Its just me playing around and trying to be clever.The way FizzBuzz can be expressed as a Monoid is cool. The rest is just plumbing.

    mconcat [Just "Fizz", Just "Buzz"] = Just "FizzBuzz"
    mconcat [Just "Fizz", Nothing    ] = Just "Fizz"
    mconcat [Nothing    , Nothing    ] = Nothing
Note that this requires {-# LANGUAGE MonadComprehensions #-} to compile. Thats for the sugar used when constructing the triggers.
2 comments

If you're going to use the (->) Monad instance, why not:

  {-# LANGUAGE MonadComprehensions #-}

  import Data.Maybe (fromMaybe)
  import Data.Monoid (mconcat)
  import Control.Applicative ((<*>))

  pam = flip map
  fizzbuzz i trigs = pam [i..] $ fromMaybe . show <*> mconcat . trigs
  
  ans = fizzbuzz 1 $ \i -> [["Fizz" | i `rem` 3 == 0]
                           ,["Buzz" | i `rem` 5 == 0]
                           ]
  
  main = mapM_ putStrLn $ take 100 ans
I'm sure that Haskell can do better than that in the readability department.
It can, I was just trying to be clever :P

For one, I don't need to drag monads into function composition:

    fizzbuzz i triggers = map (\x -> fromMaybe (show x) $ 
                                               mconcat $ triggers x) 
                              [i..]

    fizzbuzz 1 $ \i -> [["Fizz" | i `rem` 3 == 0]
                       ,["Buzz" | i `rem` 5 == 0]
                       ]