|
A first application with HappstackBefore we dive straight into the code that actually runs this tutorial, I want to take some time to walk you through the very basics of writing & running a Happstack application. So first, fire up that trusty GHCi and import Happstack.Server. Then follow along with the steps below.
Now if you check your localhost:8080 you should see the text "Hello World!". Congratuations, you've now succesfully written & run a Happstack application. Now we'll take a little bit of time and explain what just happened. First, look again at the type of simpleHTTP. Conceptually, we can already take a stab at what this means. simpleHTTP is a function that will take in a Conf and handler and then run the Happstack webserver. A Conf is, as can be seen, a fairly simple data type. It consists of the port number to listen on and a default validator to use for the application. We'll come back to using validators in a future chapter, but for now let's just say that they can be a convenient debugging tool and probably not something you want to use in a live application. Now let's take a look at what makes up a ServerPartT:
My Goodness! That's a lot of instances! Some important ones we'll be using are the Monoid, Functor, MonadIO, and MonadTrans instances. The others will transparently enable much of the machinery of Happstack but don't require us to actively think about them. I want to make one final note about simpleHTTP: did you notice the type restriction (ToMessage a) on the return type of the ServerPartT? Let's again whip out ghci and take a look at this class. ghci>:i ToMessage
You many not need to call these methods explicitly for your own applications, but the ToMessage instance for the return type of your ServerPartT is going to determine how your handler's response will be displayed. The minimal complete definition of ToMessage is toMessage. The default content type will be "text/plain". Now, we'll move on to a slightly more complicated example and the slightly uglier cousin of simpleHTTP: simpleHTTP' ghci>:i simpleHTTP'
Please don't be alarmed by that type signature. This function is actually very simple for any cases you're likely to use. simpleHTTP itself is equivalent to simpleHTTP' id. Take a look at the source of StateTExample.hs and then try running StateTExample with, for example, runghc StateTExample.hs. If you navigate to localhost:8880 then you should see the little lonely number 1. Try it a few more times! Has the number changed at all? This is because each handling of a request will apply the (flip evalStateT 0) function, hence the state is restarted every time. This example isn't the most useful because of its simplicity, but for complicated computations in the request handling the ability to have an inner monad other than IO can be convenient. Next we'll be talking about a number of the conveniant combinators in an extended example. |