{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import Data.Monoid
import Data.String
import Network.Wai.Middleware.RequestLogger
import Web.Scotty
data FullName = FullName { firstName :: String, lastName :: String }
lastFirst :: FullName -> String
lastFirst fn = lastName fn ++ ", " ++ firstName fn
main = scotty 3000 $ do
middleware logStdoutDev
get "/lastfirst/:fn/:ln" $ do
fullName <- FullName <$> param "fn" <*> param "ln"
html $ fromString (lastFirst fullName)
You may notice that the last part of the code use applicative function to construct a record, can someone explain why it shouldn't be created as usual?
This is because param "fn"
is not a String
, but an ActionM
which produces a String
. We don't want to store the action inside FullName
, we want to run the action, take its result, and store that.
We could run the actions as follows
get "/lastfirst/:fn/:ln" $ do
fn <- param "fn"
ln <- param "ln"
let fullName = FullName fn ln
html $ fromString (lastFirst fullName)
but the applicative syntax is easier to read.