【问题标题】:How to parse yesod-form parameters into Haskell values如何将 yesod-form 参数解析为 Haskell 值
【发布时间】:2017-05-30 17:16:54
【问题描述】:

以下代码来自 yesod-simple 脚手架创建的 Home.hs 文件。 我喜欢对文本输入进行简单的字符串操作,但不知道如何将其解析为 Text 值。 例如,如何在 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")

【问题讨论】:

    标签: haskell yesod yesod-forms


    【解决方案1】:

    不幸的是,这是文档和沟通方面的错误。

    给定

    lookupPostParam :: (MonadResource m, MonadHandler m) => Text -> m (Maybe Text)
    

    读者的意思是推断m不仅是MonadResouceMonadHandler,而且也是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 堆栈(MonadHandlerMonadResource)“感染”了您的代码。这是故意的,以便通过类型检查器限制您仅在预期的 Yesod 环境/状态机/上下文/任何内容中运行此功能。

    然而

    您正在使用 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 =&gt; Functor (AForm m) 实例。知道我们确实在一个 monad 中(Handler monad)意味着我们可以在areq textField textSettings Nothing 返回的值上使用fmap 和它的中缀兄弟&lt;$&gt;。这允许我们将作用于Text 的任意函数提升到AForm m 堆栈中。例如,这里我们从Text -&gt; Text 转到AForm Handler Text -&gt; AForm Handler Text

    希望对您有所帮助。

    【讨论】:

    • 我在网上某处复制了 lookupPostParam 的类型:下次我将使用 hackage 站点进行此操作,但我不知道如何找到我安装的 yesod-form 的版本。命令 'stack exec -- yesod version' 返回 yesod-bin 1.5.2.3。安装符合快速入门指南,在 Ubuntu 16.04 LTS 系统上。我已经尝试了您的建议,但仍然出现“无法匹配预期类型”错误。但是,您的回答给了我一些进一步研究的提示,因此我单击了复选标记。谢谢!
    • 我从hackage.haskell.org/package/yesod-core-1.4.33/docs/… 得到了这个,但我想你已经明白了;找出你正在使用堆栈的版本包尝试stack list-dependencies
    猜你喜欢
    • 2019-02-25
    • 1970-01-01
    • 2012-01-26
    • 2013-05-16
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多