packages feed

fizzbuzz-as-a-service-0.1.0.0: app/fizzbuzz-server.hs

{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Prelude

import Control.Concurrent (threadDelay)
import Data.ByteString (ByteString)
import Data.Semigroup ((<>))
import Data.String (fromString)
import Numeric.Natural (Natural)

import qualified Network.Simple.TCP as Net

import qualified Options.Applicative as Opt

main :: IO ()
main =
  getArgs >>= \args ->
  Net.serve Net.HostAny (argPort args) accept

accept :: (Net.Socket, Net.SockAddr) -> IO ()
accept (s, _) =
    go 1
  where
    go i =
      Net.send s (fizzbuzz i) *>
      Net.send s "\n" *>
      threadDelay 500000 *>
      go (succ i)

fizzbuzz :: Natural -> ByteString
fizzbuzz i =
  case (i `mod` 3 == 0, i `mod` 5 == 0) of
    (True,  False) -> "Fizz"
    (False, True)  -> "Buzz"
    (True,  True)  -> "Fizz buzz"
    (False, False) -> fromString (show i)

data Args = Args
  { argPort :: String
  }

getArgs :: IO Args
getArgs =
  Opt.execParser $
  Opt.info (Opt.helper <*> argP) (Opt.header "FizzBizz as a service.")

argP :: Opt.Parser Args
argP = Args <$> portP

portP :: Opt.Parser Net.ServiceName
portP =
  Opt.strOption $
  Opt.long "port" <>
  Opt.short 'p' <>
  Opt.metavar "PORT" <>
  Opt.help "Service port to bind."