## Introduction This tutorial is the first in a series of 4 tutorials on how to build a file hosting service using Yesod. Site visitors will be able to upload collections of files, and later download those same files to a different computer. We'll touch on issues you will likely encounter when writing any web app such as HTML generation, styling, maintaining application state, and managing form data. The main goal of the tutorials are to show you how to get started writing web applications using Haskell and the Yesod Web Framework. Each entry will build on the last as we write a complete application from start to finish. The Yesod Web Framework is a complete package for developing web applications. Yesod projects execute as an HTTP server that can be self-hosted or interface with an existing server using methods such as FastCGI. A unique system of mapping URL paths to handler functions make it so that broken links trigger a compile-time error. Several miniature domain-specific languages aid in the making of persistence layers, routing systems, and templates. Fragments of HTML, CSS, and JavaScript can be packaged into components called widgets. These can be combined with each other efficiently so that clients receive a single copy of everything they need. Many of Yesod's features will be left out of discussion. One of these is Yesod's built-in support for automated testing. Another is Yesod's ability to run applications such that templates are automatically reloaded at runtime. ## Conventions As we go I will follow a set of conventions in how examples appear, programming constructs are referred to, and new material is presented. Being aware of these conventions from the beginning may help you follow along. When I refer to the name of a function, data type, or class which is found in within the libraries supported by FP Complete, it will often be hyperlinked to documentation. Examples might be the lookup function from the Data.List module. When I quote a short expression of code, refer to a name defined within the project, or otherwise embed a programming language fragment into the English prose, it will appear `like this`. These tutorials are written using the FP School of Haskell learning site. Most of the provided code samples will be executable. These will have the usual FP School of Haskell "play" button in the upper-right hand corner. You are encouraged to experiment with these example applications, and to execute the modifications that you make. Over the course of this series the project will grow, so in each new section we will only show files where changes have occurred. You will always be able to see the hidden code by clicking on buttons which will appear in the upper-right hand corner of the example. Pay special attention to highlighted blocks within the examples. These are the lines which have been changed or added. Comments represent lines of code as they were in a previous example. # Minimal Example Let's start by writing a minimal web site that serves a single page of static HTML. I'll walk you through the code line-by-line. Later on we will break this application into several files, but everything will fit into the same pattern. ``` active haskell web {-# START_FILE Main.hs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Main where import Yesod data App = App instance Yesod App mkYesod "App" [parseRoutes| / HomeR GET |] getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle "File Processor" toWidget [whamlet|

Previously submitted files |] main :: IO () main = warpEnv App ``` ## Language extensions ``` haskell {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} ``` The first block of text is a collection of compiler pragmas declaring that several language extensions will be used. We will briefly describe their purpose here. See the GHC user guide for more information. ### OverloadedStrings Overloaded strings allows us to use string literals where we would not otherwise be able to. Take a look at the line reading, `setTitle "File Processor"`. The setTitle action expects the type of its argument to be Html, and we've supplied a string literal. Standard Haskell would fix the type of our string to `[Char]` or `String`, and report a type error. Using overloaded strings is not required, but frees us from having to manually convert string literals to the types we want. Without this extension we would have needed to import the `Data.String` module and set the page title with, `setTitle . fromString $ "File Processor"`. We recommend trying this out as an exercise. Disable the OverloadedStrings extension, and read the compiler error. Once you have done this, change the line starting with "setTitle" so that the program will run. A solution is included below. @@@ ``` active haskell web {-# START_FILE Main.hs #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Main where import Data.String import Yesod data App = App instance Yesod App mkYesod "App" [parseRoutes| / HomeR GET |] getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle . fromString $ "File Processor" toWidget [whamlet|

Previously submitted files |] main :: IO () main = warpEnv App ``` @@@ ### TemplateHaskell and QuasiQuotes The `TemplateHaskell` language extension enables compile-time metaprogramming. Yesod uses this in a number of places to reduce and simplify the amount of code we need to write. Much of our application's boilerplate will be written for us. Any function calls made from the top level of a source file are examples of Template Haskell in use. The line reading `mkYesod "App" ...` is one such place. We will describe what this line does later on. The `QuasiQuotes` language extension is an addition to Template Haskell which allows us to embed domain specific languages directly into Haskell source files. Yesod includes several of these small languages, and our first example uses 2 of them. The extension gets its name from the `[|` and `|]` tokens that surround it. I'll highlight this extension's usage below: ``` haskell mkYesod "App" {-hi-}[parseRoutes| / HomeR GET |]{-/hi-} getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle . fromString $ "File Processor" toWidget {-hi-}[whamlet|

Previously submitted files |]{-/hi-} ``` ### TypeFamilies The `TypeFamilies` language extension is used internally by Yesod. We will not be using it directly in this tutorial, but the extension will need to be enabled in a few modules. ## Module and Import Declarations ``` haskell module Main where import Yesod ``` Our hello world application includes everything in a single file. When we expand on it I will show you the recommended way to organize a Yesod project. The Yesod module exports most of the basic functionality for writing a Yesod application. ## Defining the Foundation Type ``` haskell {-hi-}data App = App{-/hi-} instance Yesod App ``` All Yesod sites contain a single "foundation" type. This type is used to hold references to any state that the site needs to maintain. The type is constructed once in the application's `main` function, and remains in memory until the program terminates. Since our example has no state, the `App` constructor has no fields. ## Instantiating the Yesod Typeclass ``` haskell instance Yesod App ``` Our `App` data type has been made an instance of the `Yesod` type class. We can now supply an `App` to functions which accept instances of Yesod as an argument. The Yesod type class includes many methods. They all contain default implemantations that can be overridden. By writing `instance Yesod App`, we've declared that all of the default methods should be used. ## Automatically Generating Boilerplate. ``` haskell mkYesod "App" [parseRoutes|/ HomeR GET|] ``` The mkYesod template haskell function generates most of the boilerplate needed to tie our `App` data type and the Yesod type class together into a complete application. The first argument is the name of our data type as a literal string. The second argument is a declaration of our site's routes. Everything between "[parseRoutes|" and "|]" is not Haskell, but a miniature language for declaring how URLs should map to handler actions. The string, "/ HomeR GET", says that our site will listen for HTTP GET requests at the root path, and will pass those requests to a handler function named getHomeR. Yesod's mkYesod Template Haskell function generates data types and type aliases that are used by the rest of our application. One such type alias is `Handler`, which is used in handler functions. ## Writing Route Handler Actions ``` haskell getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle "File Processor" toWidget [whamlet|

Previously submitted files |] ``` Any route mentioned in our parseRoutes quasi-quoted fragment must have an associated handler function. There is a convention for how handler functions should be named. Recall that our route definition was `[parseRoutes|/ HomeR GET|]`. The `HomeR` fragment becomes the name for our home page if we ever want to generate a hyperlink back to it. Handler actions always have names starting with the HTTP verb they handle followed by the name of the route. In the first line we see defaultLayout being called. This is one of the Yesod type class's methods. It operates in a special handler monad that the call to mkYesod generated for us. The defaultLayout method takes a "widget" action as an argument, and produces a block of HTML to be used in the final HTTP response. The next 3 lines make up our widget action. The call to setTitle specifies what ends up in our final HTML's <title> tag. Yesod uses a templating language called Hamlet to produce HTML. This is what you see in the block starting with `toWidget [whamlet|` and ending in `|]`. Hamlet supports a number of features that will be useful to us later on. For now we're just generating static HTML that will end up in our `` tag. ## Starting the Server Process ``` haskell main :: IO () main = warpEnv App ``` The `main` action is where we initialize configurations, open database connections, or perform other up-front processes. Typically our foundation data type, `App` in this case, will hold references to anything needed during execution. # A Closer Look at Hamlet Earlier on We gave you a glimps of using Hamlet to generate static HTML. We want to end this episode by showing you a few other features of Hamlet so you will have something to experiment with. ## Nesting Hamlet's syntax is similar to HTML in that text is marked up with angle bracketted tags. You may have noticed in the example given above that We did not type a closing tag. This is because Hamlet uses whitespace for nesting. As an example, here is how you would make an unordered list: ``` active haskell web {-# START_FILE Main.hs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Main where import Yesod data App = App instance Yesod App mkYesod "App" [parseRoutes| / HomeR GET |] getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle "File Processor" toWidget [whamlet|

Previously submitted files {-hi-}