将标签值作为文本/字符串传递给表单

时间:2013-07-27 20:55:59

标签: haskell yesod

这是我的问题的后续问题:Extracting database field values inside a Handler

我想从数据库中提取一些信息并将其作为表单的标签值传递。但是,我收到类型错误。

下面的简单演示(来自Yesod Book的shell代码):

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE QuasiQuotes           #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeFamilies          #-}
import           Control.Applicative ((<$>), (<*>))
import           Data.Text           (Text)
import           Data.Time           (Day)
import           Yesod
import           Yesod.Form.Jquery

data App = App

mkYesod "App" [parseRoutes|
/ HomeR GET
|]

instance Yesod App

instance RenderMessage App FormMessage where
    renderMessage _ _ = defaultFormMessage

instance YesodJquery App

data Person = Person
    { personName          :: Text
    }
  deriving Show

personForm :: Text -> Html -> MForm Handler (FormResult Person, Widget)
personForm n1 = renderDivs $ Person
    <$> areq textField n1 Nothing  -- Changing n1 to "Name" works just fine. 


getHomeR :: Handler Html
getHomeR = do
    (widget, enctype) <- generateFormPost $ personForm "test"
    defaultLayout
        [whamlet|
            <p>
                The widget generated contains only the contents
                of the form, not the form tag itself. So...
        |]


main :: IO ()
main = warp 3000 App

当我使用runhaskell运行程序时,出现以下错误:

Couldn't match expected type `FieldSettings site0'
            with actual type `Text'
In the second argument of `areq', namely `n1'
In the second argument of `(<$>)', namely
  `areq textField n1 Nothing'
In the second argument of `($)', namely
  `Person <$> areq textField n1 Nothing'

我也试过 (FieldSettings n1 Nothing Nothing Nothing []) 但没有运气。关于如何将标签值传递给areq的任何想法?

1 个答案:

答案 0 :(得分:1)

让我们看一下areq

的类型
areq :: (RenderMessage master msg, RenderMessage master FormMessage) => Field sub master a -> FieldSettings msg -> Maybe a -> AForm sub master a

因此areq函数不希望Text值作为其第二个参数,它需要FieldSettings msg。那么当你在源代码中写“Name”时,它的工作原理是什么?

查看the documentation for yesod-formsFieldSettings的文档,我们发现它是一个具有IsString实例的数据类型。查看the source code中的具体实例 我们看到了:

instance (a ~ Text) => IsString (FieldSettings a) where
fromString s = FieldSettings (fromString s) Nothing Nothing Nothing []

因此,每次在源代码中编写String时(如果启用了OverloadedStrings扩展),编译器将插入fromString实例的内容。

但是,您不想输入String,而是想要从Text值创建FieldSettings。展望未来,我们发现FieldSettings的第一部分是SomeMessage,检查documentation yet againsource我们看到可以创建SomeMessage使用SomeMessage构造函数。

personForm :: Text -> Html -> MForm Handler (FormResult Person, Widget)
personForm n1 = renderDivs $ Person
    <$> areq textField (FieldSettings (SomeMessage n1) Nothing Nothing Nothing []) Nothing