“Hello World”, Yesod style…

Here we go! Without further ado, borrowed in part from Developing Web Applications with Haskell and Yesod
(although the discussion that follows is mine, taken from what I now understand about the code).


{-# LANGUAGE TypeFamilies, QuasiQuotes, MultiParamTypeClasses,
TemplateHaskell, OverloadedStrings #-}

import Yesod

data HelloWorld = HelloWorld

mkYesod "HelloWorld" [parseRoutes|
/ HomeR GET
|]

instance Yesod HelloWorld

getHomeR :: Handler RepHtml
getHomeR = defaultLayout [whamlet|Hello World!|]

main :: IO ()
main = warpDebug 3000 HelloWorld

This makes use of several extensions not part of the Haskell standard:

  • Type families
  • Quasiquoting, used for lots of little domain specific languages (DSLs) like the one used to specify the binding between the front controller and handler methods
  • Templated Haskell — a lot of Yesod code generates other code that actually supports your Web application

We’re going to create one data type that’s the foundation of our Web application. In a bigger Web app, this data type would have all the stuff needed for initialization, too — stuff like bringing up a persistent database connection. Our foundation is HelloWorld.

The next bit of code uses the parseRoutes DSL to set up the binding between the Web application’s URIs and the functions that the framework invokes when requests for those URIs come in — the “resource”, as denoted by the trailing R in the function’s name. The syntax is path to resource, then whitespace, then the resource, then more whitespace, then the HTTP method used to access the resource.

We indicate that HelloWorld is an instance of Yesod, the type class encapsulating the behavior of Yesod’s framework.

Next, we declare the resource handling function for /. The framework expects the resource handler to be named as a concatenation of the HTTP method used to access the resource and the resource itself — hence getHomeR is the resource for handling GET requests of the HomeR resource, which we bound to the path /. It’s of type Handler RepHTML, indicating that it returns HTML. Ours uses the whamlet quasiquoter to take an HTML-based DSL and return actual well-formed HTML to the client. As I’ll get into in a later post, you can evaluate Haskell and do other nifty stuff in the context of the various DSLs for content here — it’s pretty cool. Yesod refers to these bits of HTML as widgets, and they can be put in different files so you can have a web page built up of small, reusable widget components, each written in a DSL for HTML called Hamlet.

Our handler just returns Hello World!.

Next up, we have our main function, invoked when the application starts. main uses a built-in web server, Warp, running in this case on port 3000, wired to the HelloWorld class.

We can run all of this using runhaskell helloworld.hs on our local development box, and we’re rewarded with a running Web application on port 3000 — to hit it, start the application in a terminal window, and then go to http://localhost:3000 in a browser window. You can see what HTML the framework produced by choosing “View source”, too.

Apparently, you don’t have to deploy with Warp, although some people do. You can also tether this to a CGI, or even deploy it in a stand-alone WebKit application! This last idea really interests me — you could build a pretty complicated application using Yesod and WebKit, and package it up as a stand-alone binary, I guess. You’d be limited, of course, to what WebKit could present, but with what JavaScript and HTML5 can do together, that’s an interesting way to slap a nice UI on a larger Haskell project, especially if it’s backed by a SQLite database for data storage. I’m going to have to think some more about that.

Next up, expect either some musings on that score, or perhaps a more in-depth look at Hamlet, the HTML templating language! In the mean time, I encourage you to play around with the resource DSL set up by parseRoutes — try adding content to your “application”.