1

下面的代码来自 yesod-simple 脚手架创建的 Home.hs 文件。我喜欢对文本输入进行简单的字符串操作,但不知道如何将其解析为 Text 值。例如,如何在 fileDescription 上使用 toUpper?我试过使用lookupPostParam,但我正在努力使用它的类型签名:

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

主页.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")
4

1 回答 1

1

不幸的是,这是文档和沟通中的一个错误。

给定

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

读者的意思是推断m不仅是 aMonadResouce和 a MonadHandler,而且是Monad。这行小小的代码将很多意图打包成一个非常小的句子;如此多的 Haskell 库使用都是隐含的和潜台词的,这是一个缺陷。例如,要在这种类型toUpperText内部调用,您应该这样做:

{-# 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) 已经“感染”了您的代码。这是故意的,以便通过类型检查器限制您仅在预期的 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 => Functor (AForm m)实例。知道我们确实在一个 monad(Handlermonad)中意味着我们可以在返回的值上使用fmap它的中缀兄弟。这允许我们将作用于堆栈的任意函数提升到堆栈中。例如,这里我们从到。<$>areq textField textSettings NothingTextAForm mText -> TextAForm Handler Text -> AForm Handler Text

希望有帮助。

于 2017-05-28T17:47:59.403 回答