Skip to content

Instantly share code, notes, and snippets.

@philandstuff
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save philandstuff/dbaeac98593cf64084ab to your computer and use it in GitHub Desktop.
Save philandstuff/dbaeac98593cf64084ab to your computer and use it in GitHub Desktop.
{-# LANGUAGE ExistentialQuantification #-}
import Data.Foldable
import Data.Set (Set)
import qualified Data.Set as Set
import Prelude hiding (mapM_)
data FizzBuzzTag = Fizz | Buzz deriving (Eq, Ord, Show)
type FizzBuzz = Set FizzBuzzTag
showSetAscending :: Show a => Set a -> String
showSetAscending s = foldMap show (Set.toAscList s)
fizz :: Integral a => a -> FizzBuzz
fizz n = case n `rem` 3 of
0 -> Set.singleton Fizz
_ -> Set.empty
buzz :: Integral a => a -> FizzBuzz
buzz n = case n `rem` 5 of
0 -> Set.singleton Buzz
_ -> Set.empty
fizzbuzz :: Integral a => a -> FizzBuzz
fizzbuzz n = fizz n `Set.union` buzz n
data FB = forall a. (Show a, Integral a) => FB (Either a FizzBuzz)
fb :: (Show a, Integral a) => a -> FB
fb n = FB $ let tags = fizzbuzz n in
if Set.null tags then Left n else Right tags
instance Show FB where
show (FB x) = either show showSetAscending x
main = mapM_ (putStrLn . show . fb) [1..50]
@krisajenkins
Copy link

I think I've spotted a bug. If you make FizzBuzz a set, you lose ordering, so you might get 15 => "BuzzFizz", no?

@philandstuff
Copy link
Author

@krisajenkins the desire to get the correct ordering is exactly why I call the toAscList fn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment