Ur/Web Tutorial

Ur/Web Tutorial

Step 1

Previous | Next

We're going to create a directory urblog for our project, and in it we will create three (empty) files:

Now, to add some content to these files!


A .urp file describes the files to be included within our project. In this case, we just want to ensure that our main source file urblog.ur and its signature definition file urblog.urs are included:

No file extensions are necesary here -- the use of a filename prefix such as this one causes the inclusion of the appropriate .ur and .urs files.


A .urs file is a signature definition that describes what artifacts of our implementation will be visible to the outside world:

val main : unit -> transaction page
We start by defining only a single function main that will be visible. It takes as input values of type unit and returns a value of type transaction page. We'll describe what exactly that means a little later.


The .ur file holds actual implementation code. According to the signature we provided in urblog.urs, we are obligated to provide a function called main, so let's go ahead and do that:

fun main () = return <xml>

If you're used to working in a programming language that treats HTML and XML as strings, then this might look a little surprising. Within Ur/Web, XML fragments such as these are first-class values (in exactly the same way as integers, strings or booleans might be). The use of return takes us back to the use of the type transaction page earlier. The XML fragment has the type page, and return makes this expression part of a transaction, which is a monad in the style of the Haskell IO monad.

Putting it all together

OK, so we've got our source files. You can compile it all by running:

urweb urblog
from inside the urblog directory. This should result in a binary called urblog.exe.

If your system is anything like mine, you can run this binary using a command like ./urblog.exe, which results in output such as:

urblog # ./urblog.exe 
Database connection initialized.
Listening on port 8080....
Database connection initialized.
Database connection initialized.
Marvelous! The stand-alone webserver associated with your application is now listening for connections on port 8080. The exact URL is munged slightly by Ur/Web, such that your module name with the first letter upper-cased is the first URI component, followed by the name of any function that is visible outside the module (i.e. roughtly any appropriately-typed functions that are included in the urblog.urs file, or any appropriate-typed functions that these depend upon). Putting it all together, we can access our application's main function at this URL:


(Note: This is a localhost URL. You must have the server running on your local machine, and have appropriate firewall/connection settings to permit you to make a connection to your local machine on port 8080).

If all of that worked, you should see a not-particularly-exciting web application featuring the word 'UrBlog' on a blank page. If it didn't work, you might have done something wrong, or there could be something wrong with your configuration. Now might be a good time to join the #ur IRC channel on Freenode.

Previous | Next