summaryrefslogtreecommitdiff
path: root/Haskell-book/26/Exercises/app/Main.hs
blob: 6bfe6bb83e94e1942e40813ac237f03750745177 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Reader
import Data.IORef
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as TL
import System.Environment (getArgs)
import Web.Scotty.Trans ( ScottyT(..)
                        , ActionT(..)
                        , scottyT
                        , get
                        , html
                        , param )

data Config =
    Config {
        -- that's one, one click!
        -- two...two clicks!
        -- Three BEAUTIFUL clicks! ah ah ahhhh
        counts :: IORef (M.Map Text Integer)
      , prefix :: Text
    }

type Scotty = ScottyT Text (ReaderT Config IO)

bumpBoomp :: Text
    -> M.Map Text Integer
    -> (M.Map Text Integer, Integer)
bumpBoomp k m =
    let (maybeCount, newMap) = M.insertLookupWithKey (\_ _ oldCount -> oldCount + 1) k 1 m
    in case maybeCount of
        Nothing -> (newMap, 1)
        Just oldCount -> (newMap, oldCount + 1)

app :: Scotty ()
app =
    get "/:key" $ do
        unprefixed <- param "key"
        prefix <- lift $ asks prefix
        let key' = mappend prefix unprefixed
        counts <- lift $ asks counts
        (newMap, newInteger) <- liftIO $ bumpBoomp key' <$> readIORef counts
        liftIO $ writeIORef counts newMap
        html $ mconcat [ "<h1>Success! Count was: "
                       , TL.pack $ show (newInteger :: Integer)
                       , "</h1>"
                       ]

main :: IO ()
main = do
    [prefixArg] <- getArgs
    counter <- newIORef M.empty
    let config = Config {counts = counter, prefix = TL.pack prefixArg}
        runR = flip runReaderT config
    scottyT 3000 runR app