Day 05 Mastery

Real-World Haskell: Web & Concurrency

Haskell excels at high-performance, correct server programs. Today covers the Scotty web framework, concurrent programming with STM, and packaging with Cab

~1 hour Hands-on Precision AI Academy

Today's Objective

Cabal is Haskell's build tool and package manager.

01

Scotty Web Framework

Scotty is a lightweight web framework inspired by Ruby's Sinatra. Routes are defined with get, post, put, delete, taking a pattern and an action in the ActionM monad. param extracts path/query parameters; json sends JSON responses; html sends HTML. Scotty runs on Warp, a high-performance Haskell HTTP server — benchmarks show Warp handling hundreds of thousands of requests per second.

02

Software Transactional Memory (STM)

STM provides composable, lock-free concurrency. TVar is a shared mutable variable. atomically executes a transaction: all reads and writes succeed together or the transaction retries from scratch. No deadlocks possible — STM detects conflicts automatically. This is far simpler than mutex-based concurrency: you cannot forget to acquire a lock because the type system forces all shared state through atomically.

03

Cabal and Stack

Cabal is Haskell's build tool and package manager. A .cabal file lists dependencies, modules, and build options. Stack wraps Cabal with reproducible builds via LTS (Long Term Support) Stackage snapshots — a known set of mutually compatible package versions. Create a project: 'stack new myproject', add dependencies to package.yaml, run 'stack build' and 'stack test'. Hackage hosts 16,000+ Haskell packages.

haskell
haskell
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Control.Concurrent.STM
import Data.Text.Lazy (Text)
import qualified Data.Map.Strict as Map

type KVStore = TVar (Map.Map Text Text)

main :: IO ()
main = do
  store <- newTVarIO Map.empty
  scotty 3000 $ do
    -- GET /kv/:key
    get "/kv/:key" $ do
      k <- param "key"
      m <- liftIO $ readTVarIO store
      case Map.lookup k m of
        Nothing -> text "Not found"
        Just v  -> text v
    -- PUT /kv/:key with body as value
    put "/kv/:key" $ do
      k <- param "key"
      v <- body
      liftIO $ atomically $
        modifyTVar store (Map.insert k (lazyTextFromStrict v))
      text "OK"

  where lazyTextFromStrict = id  -- simplified
💡
Use Data.Text instead of String for all text processing. String is [Char] — a linked list of characters — which is 5-10x slower and 3x more memory than Text's packed UTF-16 representation.

Supporting References & Reading

Go deeper with these external resources.

Docs
Real-World Haskell: Web & Concurrency Official documentation for haskell.
GitHub
Real-World Haskell: Web & Concurrency Open source examples and projects for Real-World Haskell: Web & Concurrency
MDN
MDN Web Docs Comprehensive web technology reference

Day 5 Checkpoint

Before moving on, confirm understanding of these key concepts:

Course Complete
Return to Course Overview