(comments)

原始链接: https://news.ycombinator.com/item?id=44071960

A Hacker News thread discusses using Monoids for FizzBuzz, inspired by a blog post. throwaway81523 criticizes the Monoid approach as overly complex and limiting, specifically for variations requiring spaces and an exclamation point. They suggest using lists and `intercalate` for better clarity and flexibility, providing a code snippet that handles Fizz, Buzz, and Bazz up to 110. kqr offers an alternative Monoid implementation using `newtype Words`, but concedes lists might be clearer. lgas shares a similar, simpler implementation from the past, noting its limitation to divisibility rules compared to the blog post's arbitrary predicates. The general consensus leans towards preferring lists over Monoids for this specific problem due to readability and adaptability.

相关文章
  • 通过幺半群理解FizzBuzz 2025-05-26
  • (评论) 2025-05-23
  • (评论) 2025-05-25
  • (评论) 2025-05-27
  • (评论) 2025-05-20

  • 原文
    Hacker News new | past | comments | ask | show | jobs | submit login
    FizzBuzz Through Monoids (entropicthoughts.com)
    14 points by kqr 1 day ago | hide | past | favorite | 3 comments










    Code is a little too fancy though it's easy to fall into that temptation with Haskell. Particularly though, using the Monoid instance on strings ties you to concatenating the strings together. There was an example the other day where the strings had to be separated by spaces and terminated by an exclam point ("Fizz Buzz!"). My solution used lists straightforwardly instead of Monoids. It goes to 110 instead of 100 since 105 is 3*5*7.

        import           Data.List (intercalate)
    
        fizzle :: Int -> String
        fizzle n =
            let ws = [(3,"Fizz"),(5,"Buzz"),(7,"Bazz")]
                a = [s | (d,s) <- ws, n`rem`d == 0]
            in case a of []        -> show n
                         otherwise -> intercalate " " a ++ "!"
    
        main = mapM_ (putStrLn . fizzle) [1..110]


    Another way to do it would be

        newtype Words = Words { getWords :: String }
    
        instance Semigroup Words where
          Words a <> Words b = Words (a <> " " <> b)
    
        instance Monoid Words where
          mempty = Words mempty
    
        fizzbuzz i =
          maybe (show i) (<> "!") . fmap getWords . mconcat $
            [ Words "fizz" <$ guard (rem i 3 == 0)
            , Words "buzz" <$ guard (rem i 5 == 0)
            ]
    
    but at this point I agree lists might be more clear.


    I wrote a similar implementation a while back[1]. The major difference is that mine only allows rules of the form "n is divisible by m" whereas the one from the post allows arbitrary predicates over n. Wouldn't be that hard to update though.

    [1] https://gist.github.com/lgastako/d4fa392cbe85cbfae7dfa5e18c1...







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



    Search:
    联系我们 contact @ memedata.com