The code below is from the Home.hs file created by the yesod-simple scaffold. I like to do simple string manipulation on text input but don't know how to parse it into a Text value. How, for example, can I use toUpper on fileDescription? I've tried using lookupPostParam but I'm struggling with it's type signature:
lookupPostParam :: MonadHandler m => Text -> m (Maybe Text)
Home.hs
module Handler.Home where
import Import
import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3)
import Text.Julius (RawJS (..))
data FileForm = FileForm
{ fileInfo :: FileInfo
, fileDescription :: Text
}
getHomeR :: Handler Html
getHomeR = do
(formWidget, formEnctype) <- generateFormPost sampleForm
let submission = Nothing :: Maybe FileForm
handlerName = "getHomeR" :: Text
defaultLayout $ do
let (commentFormId, commentTextareaId, commentListId) = commentIds
aDomId <- newIdent
setTitle "Welcome To Yesod!"
$(widgetFile "homepage")
postHomeR :: Handler Html
postHomeR = do
((result, formWidget), formEnctype) <- runFormPost sampleForm
let handlerName = "postHomeR" :: Text
submission = case result of
FormSuccess res -> Just res
_ -> Nothing
defaultLayout $ do
let (commentFormId, commentTextareaId, commentListId) = commentIds
aDomId <- newIdent
setTitle "Welcome To Yesod!"
$(widgetFile "homepage")
sampleForm :: Form FileForm
sampleForm = renderBootstrap3 BootstrapBasicForm $ FileForm
<$> fileAFormReq "Choose a file"
<*> areq textField textSettings Nothing
where textSettings = FieldSettings
{ fsLabel = "What's on the file?"
, fsTooltip = Nothing
, fsId = Nothing
, fsName = Nothing
, fsAttrs =
[ ("class", "form-control")
, ("placeholder", "File description")
]
}
commentIds :: (Text, Text, Text)
commentIds = ("js-commentForm", "js-createCommentTextarea", "js-
commentList")
This is unfortunately a fault in documentation and communication.
Given
the reader is meant to infer that
m
is not only aMonadResouce
and aMonadHandler
but alsoMonad
. This tiny little line of code packs up a lot of intent into a very small sentence; it's a wart that so much of Haskell library usage is left implicit and subtextual. For example, to calltoUpper
on theText
inside this type you are meant to do this:Note that the monad stack (
MonadHandler
,MonadResource
) has "infected" your code. This is meant to be intentional, so as to constrain you via the type checker to only run this function in the intended Yesod environment/state machine/context/whatever.However
You are using yesod-forms and it would be nice to do the same thing within that framework. As with
lookupPostParam
, we can take advantage of the monad-applicative-functor typeclasses.We can adapt this to the
Form FileForm
value that you have.I think the types of
yesod-forms
changed between releases. I'm copying my types off the latest version as of writing, 1.4.11.Here we take advantage of the
Monad m => Functor (AForm m)
instance. Knowing that we are indeed in a monad (theHandler
monad) means we can usefmap
and its infixed sibling<$>
on the value returned byareq textField textSettings Nothing
. This allows us to lift arbitrary functions acting onText
into theAForm m
stack. For example, here we went fromText -> Text
toAForm Handler Text -> AForm Handler Text
.Hope that helps.