{-# LANGUAGE LambdaCase #-}
module Main where
import Control.Monad
import System.IO
{-@ data NumberType = Normal (i :: {v:Int | v mod 3 /= 0 && v mod 5 /= 0})
| Fizz
| Buzz
| FizzBuzz @-}
data NumberType = Normal Int
| Fizz
| Buzz
| FizzBuzz
{-@ fizz :: {v:Int | v mod 3 == 0 && v mod 5 /= 0} -> NumberType @-}
fizz :: Int -> NumberType
fizz _ = Fizz
{-@ buzz :: {v:Int | v mod 3 /= 0 && v mod 5 == 0} -> NumberType @-}
buzz :: Int -> NumberType
buzz _ = Buzz
{-@ fizzbuzz :: {v:Int | v mod 3 == 0 && v mod 5 == 0} -> NumberType @-}
fizzbuzz :: Int -> NumberType
fizzbuzz _ = FizzBuzz
numberType :: Int -> NumberType
numberType i = case (i `mod` 3 == 0, i `mod` 5 == 0) of
(True, False) -> fizz i
(False, True) -> buzz i
(True, True) -> fizzbuzz i
_ -> Normal i
main :: IO ()
main = do
putStrLn "FizzBuzz v. 1.0.0"
putStr "From: "
hFlush stdout
from <- getLine
putStr "To: "
hFlush stdout
to <- getLine
forM_ (map numberType [read from .. read to]) $ \case
Normal i -> putStrLn $ show i
Fizz -> putStrLn "Fizz"
Buzz -> putStrLn "Buzz"
FizzBuzz -> putStrLn "FizzBuzz"