patternMinor
Haskell FizzBuzz with a type system
Viewed 0 times
withsystemfizzbuzztypehaskell
Problem
The core problem is simple enough, but I've developed a type system that I'm not sure about. The intention is, if the result is a number, calling
num $ fizzBuzz 16, for example, lets me retrieve 16 as an Int. However, it seems awfully repetitive, to have to mention "Fizz" so many times in the code. Can it be done better?data NoiseNum = Fizz | Buzz | FizzBuzz | Num Int
deriving (Eq)
instance Show NoiseNum where
show FizzBuzz = "FizzBuzz"
show Fizz = "Fizz"
show Buzz = "Buzz"
show (Num n) = show n
num :: NoiseNum -> Int
num (Num n) = n
fizzBuzz :: Int -> NoiseNum
fizzBuzz n
| n `mod` 15 == 0 = FizzBuzz
| n `mod` 3 == 0 = Fizz
| n `mod` 5 == 0 = Buzz
| otherwise = Num n
main = do
mapM_ putStrLn $ map (show . fizzBuzz) [1..100]Solution
In the issue 23 of The Monad.Reader, there is a nice discussion of FizzBuzz and how to solve it efficiently in Haskell. The efficiency being in terms of future extensions such as "output Bazz if it's a multiple of 7, FizzBazz if it's a multiple of 21, (...)". The proposed solution is linear in the number of conditions.
The final answer goes something like this (but I'd advise you to go through the paper: it's a pretty nice read!):
The final answer goes something like this (but I'd advise you to go through the paper: it's a pretty nice read!):
fizzbuzz n = (test 3 "Fizz" . test 5 "Buzz") id (show n)
where test d s x | n `mod` d == 0 = const (s ++ x "")
| otherwise = xCode Snippets
fizzbuzz n = (test 3 "Fizz" . test 5 "Buzz") id (show n)
where test d s x | n `mod` d == 0 = const (s ++ x "")
| otherwise = xContext
StackExchange Code Review Q#56901, answer score: 3
Revisions (0)
No revisions yet.