Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm probably guilty of this, as a guy who is learning Haskell. FizzBuzz can be just

    main = putStrLn $ unlines $ map fizzer [1..100] where
        fizzer n | n % 15 == 0  = "FizzBuzz"
                 | n %  3 == 0  = "Fizz"
                 | n %  5 == 0  = "Buzz"
                 | otherwise    = show n
but I think the first time I tried to solve it in Haskell I had something more like:

    import Data.Monoid (Monoid, mconcat)
    import Data.Maybe (catMaybes)

    specialcases :: (Monoid y) => [x -> Maybe y] -> x -> Either x y
    specialcases rules x = case catMaybes (map ($ x) rules) of
        [] -> Left x
        xs -> Right (mconcat xs)

    ifDivBy :: Integer -> x -> Integer -> Maybe x
    ifDivBy n x m = if m `mod` n == 0 then Just x
                                        else Nothing

    main = putStrLn $ unlines $ strings where
        strings = map (either show id) cases
        fizzer = specialcases [ifDivBy 3 "Fizz", ifDivBy 5 "Buzz"]
        cases = map fizzer [1..100]
This is basically thinking about an imperative problem the "wrong way around": starting with the logical distinction between "we're in a special case" and "we're in the normal case" and building everything else around it. (Also, who is ever going to use that Monoid instance? Replace `id` with `concat` and you can just remove `Data.Monoid` altogether -- and if you really wanted it generic, taking an explicit `y -> y -> y` and using `foldl1` would be more flexible anyway.)


Ah! I had this same(-ish) idea but couldn't figure out how to write it. And when I realized how much time I was spending on Fizz Buzz forced myself to stop.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: