This post will introduce some magic that you’ll use on a daily basis when using Yesod. This magic is mostly related to connection with the outside world – while Handler and Widget have IO in their type signatures, there are recommended ways of dealing with it – and this recommended way includes a foundation datatype.

Foundation datatype is a type that is accessible in all your Widget‘s and Handler‘s. In fact, it is even in the signature of your application – in Yesod App, App is your foundation datatype (that’s the name in the default scaffolding, you can change it if you wish to). You can keep anything there – default scaffolding puts there some server settings, connection pools, logger etc., but you can put virtually anything there – it’s just a typical data type.

This time we’re going to use it in a very simple way – to inject application name into the widgets and use it in the title – but on future posts we’ll be using the foundation value in much more sophisticated scenarios, such as database access or configuration. First let’s add the name to our data type – since this is just a tutorial, we’ll add it as a top-level field. So, in Foundation.hs change the definition of data App to

data App = App
    { appSettings    :: AppSettings
    , appStatic      :: Static -- ^ Settings for static file serving.
    , appConnPool    :: ConnectionPool -- ^ Database connection pool.
    , appHttpManager :: Manager
    , appLogger      :: Logger
    , appName        :: Text
    }

Next step, initialization. In Application.hs in code of makeFoundation function add appName <- return "Project M" line. That’s it, you already have your foundation data initialized. A little magic here is performed by the following line: let mkFoundation appConnPool = App {..} – the {..} syntax binds together names that exist in the scope and create a single data record. By the way, you can also use it the other way around: App {..} <- getYesod will bring all the fields to the current scope. I believe it generally clutters the scope and should be avoided. Still, sometimes it can come in handy. getYesod is a wrapped object of the foundation type, which is usually accessed by the syntax mentioned above (app <- getYesod) – yet, it’s a typical Yesod value, so there is no real reason (except maybe convenience) to stick to this method.

In the last step we’re going to change Handler/Project.hs and it’s rendering function. Let’s change the first two lines of renderPage function to:

app <- getYesod
setTitle $ (toHtml $ (appName app)) ++ ": " ++ projectTitle

And that’s it, title on your development server should already change. I’ll change the display to format appName: projectName(projectId), by changing the where clause from projectTitle = (toHtml projectId) ++ (toHtml projectName) to projectTitle = (toHtml projectName) ++ "(" ++ (toHtml projectId) ++ ")".

That’s it for today – soon we’re going to explore the way of using databases with Yesod, but first – in the next post – we’ll have to deal with our data type and make it more useful.

Stay tuned!