Webwire

From HaskellWiki

Examples[edit]

As multiple people have asked for examples now, I'm providing some. Here is the obligatory Hello World application, which just displays a text/plain string:

import Network.Wai.Handler.Warp
import WebWire

main :: IO ()
main =
    simpleWire (run 4000) $ proc _ ->
        render -< "Hello world!" :: String

Here is a slightly more interesting example showing how to use widgets:

main :: IO ()
main =
    simpleWire (run 4000) $ proc _ -> do
        addWidget -< cssW "html { background: #aaa; }"
        addWidget -< bodyW (He.h1 (toHtml ("Hello world!" :: String)))
        renderDef -< ()

Routing works through wire combination and signal inhibition. A wire can inhibit the output signal. This normally corresponds to a 404 error, though other errors are possible. Multiple wires can be combined. If one wire inhibits, the next is tried. If all wires inhibit, their sum inhibits. On its surface this is similar to how Happstack handles routing, but has a different underlying machinery. Also here I'm using Hamlet, Lucius and the 'time' wire to demonstrate how state is managed in this FRP-based framework:

home :: WebWire site a Response
home =
    rootDir $ proc _ -> do
        t <- time -< ()
        addWidget <<< cssLinkW ^<< pathAbs -< ["style", "test.css"]
        addWidget -< hamletW [hamlet|
            <h1>Hello world!
            <p>This server has been running for #{t} seconds.|]
        renderDef -< ()


style :: WebWire site a Response
style =
    directory "style" . file "test.css" $ proc _ -> do
        render -< [lucius| html { background: #aaa; } |] (\_ _ -> "")


main :: IO ()
main =
    let apps = style <+> home in
    simpleWire (run 4000) $ proc _ -> do
        setRoot -< ["http://localhost:4000"]
        apps -< ()

For sessions you use the 'session' wire transformer. This is one of the most interesting features. The following website allows each session a maximum request rate of 10 requests per second:

home :: WebWire site a Response
home =
    rootDir $ proc _ -> do
        t <- time -< ()
        fps <- avgFps 10 -< ()
        require_ -< fps <= 10

        fpsHi <- highPeak -< fps
        fpsLo <- lowPeak -< fps

        addWidget -< hamletW [hamlet|
            <h1>Hello world!
            <p>This session has been running for #{t} seconds.
            <p>Requests per second: #{fps} (high peak: #{fpsHi}) (low peak: #{fpsLo})|]
        renderDef -< ()


main :: IO ()
main =
    simpleWire (run 4000) $ proc _ -> do
        setRoot -< ["http://localhost:4000"]
        session defSessionCfg home -< ()