throwaway81523 2 days ago

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]
  • kqr 2 days ago

    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.