# Web Development
# Servant
Servant (opens new window) is a library for declaring APIs at the type-level and then:
-
- write servers (this part of servant can be considered a web framework),
- obtain client functions (in haskell),
- generate client functions for other programming languages,
- generate documentation for your web applications
- and more...
Servant has a concise yet powerful API. A simple API can be written in very few lines of code:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Data.Text
import Data.Aeson.Types
import GHC.Generics
import Servant.API
data SortBy = Age | Name
data User = User {
name :: String,
age :: Int
} deriving (Eq, Show, Generic)
instance ToJSON User -- automatically convert User to JSON
Now we can declare our API:
type UserAPI = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
which states that we wish to expose /users
to GET
requests with a query param sortby
of type SortBy
and return JSON of type User
in the response.
Now we can define our handler:
-- This is where we'd return our user data, or e.g. do a database lookup
server :: Server UserAPI
server = return [User "Alex" 31]
userAPI :: Proxy UserAPI
userAPI = Proxy
app1 :: Application
app1 = serve userAPI server
And the main method which listens on port 8081
and serves our user API:
main :: IO ()
main = run 8081 app1
Note, Stack (opens new window) has a template for generating basic APIs in Servant, which is useful for getting up and running very quick.
# Yesod
Yesod project can be created with stack new
using following templates:
yesod-minimal
. Simplest Yesod scaffold possible.yesod-mongo
. Uses MongoDB as DB engine.yesod-mysql
. Uses MySQL as DB engine.yesod-postgres
. Uses PostgreSQL as DB engine.yesod-postgres-fay
. Uses PostgreSQL as DB engine. Uses Fay language for front-end.yesod-simple
. Recommended template to use, if you don't need database.yesod-sqlite
. Uses SQlite as DB engine.
yesod-bin
package provides yesod
executable, which can be used to run development server. Note that you also can run your application directly, so yesod
tool is optional.
Application.hs
contains code that dispatches requests between handlers. It also sets up database and logging settings, if you used them.
Foundation.hs
defines App
type, that can be seen as an environment for all handlers. Being in HandlerT
monad, you can get this value using getYesod
function.
Import.hs
is a module that just re-exports commonly used stuff.
Model.hs
contains Template Haskell that generates code and data types used for DB interaction. Present only if you are using DB.
config/models
is where you define your DB schema. Used by Model.hs
.
config/routes
defines URI's of the Web application. For each HTTP method of the route, you'd need to create a handler named {method}{RouteR}
.
static/
directory contains site's static resources. These get compiled into binary by Settings/StaticFiles.hs
module.
templates/
directory contains Shakespeare (opens new window) templates that are used when serving requests.
Finally, Handler/
directory contains modules that define handlers for routes.
Each handler is a HandlerT
monad action based on IO. You can inspect request parameters, its body and other information, make queries to the DB with runDB
, perform arbitrary IO and return various types of content to the user. To serve HTML, defaultLayout
function is used that allows neat composition of shakespearian templates.