这是我的问题的后续问题: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的任何想法?
答案 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-forms中FieldSettings
的文档,我们发现它是一个具有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 again和source我们看到可以创建SomeMessage
使用SomeMessage
构造函数。
personForm :: Text -> Html -> MForm Handler (FormResult Person, Widget)
personForm n1 = renderDivs $ Person
<$> areq textField (FieldSettings (SomeMessage n1) Nothing Nothing Nothing []) Nothing