如何将 yesod 形式的参数解析为 Haskell 值
How to parse yesod-form parameters into Haskell values
以下代码来自 yesod-simple 脚手架创建的 Home.hs 文件。
我喜欢对文本输入进行简单的字符串操作,但不知道如何将其解析为文本值。
例如,如何在 fileDescription 上使用 toUpper?
我试过使用 lookupPostParam
但我正在为它的类型签名而苦苦挣扎:
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")
不幸的是,这是文档和通信中的错误。
给定
lookupPostParam :: (MonadResource m, MonadHandler m) => Text -> m (Maybe Text)
reader 的意思是推断 m
不仅是 MonadResouce
和 MonadHandler
,而且是 Monad
。这一小行代码将很多意图打包成一个非常小的句子;这么多 Haskell 库的使用是隐含的和潜台词的,这是一个缺点。例如,要在该类型内的 Text
上调用 toUpper
,您应该这样做:
{-# language OverloadedStrings #-}
foo :: (MonadResource m, MonadHandler m) => m (Maybe Text)
foo = do
valueMaybe <- lookupPostParam "key"
case valueMaybe of
Just value ->
pure (toUpper value)
Nothing ->
Nothing
请注意,monad 堆栈 (MonadHandler
、MonadResource
) 有 "infected" 您的代码。这是故意的,以便通过类型检查器将您限制为仅 运行 在预期的 Yesod environment/state machine/context/whatever.
中使用此功能
但是
您正在使用 yesod-forms,在该框架内做同样的事情会很好。与 lookupPostParam
一样,我们可以利用 monad-applicative-functor 类型类。
我们可以根据您的 Form FileForm
值进行调整。
sampleForm :: AForm Handler FileForm
sampleForm =
FileForm <$> fileAFormReq "Choose a file"
<*> (toUpper <$> areq textField textSettings Nothing)
我认为 yesod-forms
的类型在不同版本之间发生了变化。在撰写本文时,我正在从最新版本 1.4.11 复制我的类型。
这里我们利用了Monad m => Functor (AForm m)
实例。知道我们确实在一个 monad(Handler
monad)中意味着我们可以在 areq textField textSettings Nothing
返回的值上使用 fmap
及其内嵌兄弟 <$>
。这允许我们将作用于 Text
的任意函数提升到 AForm m
堆栈中。例如,这里我们从 Text -> Text
到 AForm Handler Text -> AForm Handler Text
.
希望对您有所帮助。
以下代码来自 yesod-simple 脚手架创建的 Home.hs 文件。 我喜欢对文本输入进行简单的字符串操作,但不知道如何将其解析为文本值。 例如,如何在 fileDescription 上使用 toUpper? 我试过使用 lookupPostParam 但我正在为它的类型签名而苦苦挣扎:
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")
不幸的是,这是文档和通信中的错误。
给定
lookupPostParam :: (MonadResource m, MonadHandler m) => Text -> m (Maybe Text)
reader 的意思是推断 m
不仅是 MonadResouce
和 MonadHandler
,而且是 Monad
。这一小行代码将很多意图打包成一个非常小的句子;这么多 Haskell 库的使用是隐含的和潜台词的,这是一个缺点。例如,要在该类型内的 Text
上调用 toUpper
,您应该这样做:
{-# language OverloadedStrings #-}
foo :: (MonadResource m, MonadHandler m) => m (Maybe Text)
foo = do
valueMaybe <- lookupPostParam "key"
case valueMaybe of
Just value ->
pure (toUpper value)
Nothing ->
Nothing
请注意,monad 堆栈 (MonadHandler
、MonadResource
) 有 "infected" 您的代码。这是故意的,以便通过类型检查器将您限制为仅 运行 在预期的 Yesod environment/state machine/context/whatever.
但是
您正在使用 yesod-forms,在该框架内做同样的事情会很好。与 lookupPostParam
一样,我们可以利用 monad-applicative-functor 类型类。
我们可以根据您的 Form FileForm
值进行调整。
sampleForm :: AForm Handler FileForm
sampleForm =
FileForm <$> fileAFormReq "Choose a file"
<*> (toUpper <$> areq textField textSettings Nothing)
我认为 yesod-forms
的类型在不同版本之间发生了变化。在撰写本文时,我正在从最新版本 1.4.11 复制我的类型。
这里我们利用了Monad m => Functor (AForm m)
实例。知道我们确实在一个 monad(Handler
monad)中意味着我们可以在 areq textField textSettings Nothing
返回的值上使用 fmap
及其内嵌兄弟 <$>
。这允许我们将作用于 Text
的任意函数提升到 AForm m
堆栈中。例如,这里我们从 Text -> Text
到 AForm Handler Text -> AForm Handler Text
.
希望对您有所帮助。