Search code examples
haskellapplicativescotty

How Scotty make an Applicative constructor


{-# 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?


Solution

  • 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.