Visitor Counter - Examples - Developing Web Apps with Haskell and Yesod, Second Edition (2015)

Developing Web Apps with Haskell and Yesod, Second Edition (2015)

Part III. Examples

Chapter 26. Visitor Counter

Remember back in the good ol’ days of the Internet, when no website was complete without a little “you are visitor number 32” thingy? Ahh, those were the good times! Let’s re-create that wonderful experience in Yesod!

Now, if we wanted to do this properly, we’d store this information in some kind of persistent storage layer, like a database, so that the information could be shared across multiple horizontally scaled web servers and would survive an app restart.

But our goal here isn’t to demonstrate good practice (after all, if it was about good practice, I wouldn’t be demonstrating a visitor counter, right?). Instead, this is meant to provide a simple example of sharing some state among multiple handlers. A real-world use case would be caching information across requests. Just remember that when you use the technique shown here, you need to be careful about multiple app servers and app restarts.

The technique is simple: we create a new field in the foundation data type for a mutable reference to some data, and then access it in each handler. The technique is so simple, it’s worth just diving into the code:

{-# LANGUAGE OverloadedStrings #-}

{-# LANGUAGE QuasiQuotes #-}

{-# LANGUAGE TemplateHaskell #-}

{-# LANGUAGE TypeFamilies #-}

import Data.IORef

import Yesod

dataApp=App

{ visitors ::IORefInt

}

mkYesod "App" [parseRoutes|

/ HomeRGET

|]

instanceYesodApp

getHomeR ::HandlerHtml

getHomeR =do

visitorsRef <-fmap visitors getYesod

visitors <-

liftIO $ atomicModifyIORef visitorsRef $ \i ->

(i + 1, i + 1)

defaultLayout

[whamlet|

<p>Welcome, you are visitor number #{visitors}.

|]

main ::IO ()

main =do

visitorsRef <-newIORef 0

warp 3000 App

{ visitors =visitorsRef

}

I used IORef here, because we didn’t need anything more than it provided, but you’re free to use MVars or TVars as well. In fact, a good exercise for the reader is to modify this program to store the visitor count in a TVar instead.