如何在Yesod中为selectField构建预选选项?

时间:2018-09-15 21:53:13

标签: haskell yesod yesod-forms

This was asked before but it has no answers)。

我在数据库中有一个国家/地区列表:

share [mkPersist sqlSettings] [persistLowerCase|
Country
  name Text
  UniqueCountryName name
  deriving Show
|]

我可以显示一个表单以选择其中之一:

countries = do
  rows <- runDB $ selectList [] [Asc CountryName]
  optionsPairs $ map (\ r -> (countryName $ entityVal r, entityKey r)) rows

surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
  (countryR, countryV) <- mreq (selectField countries) "" Nothing

我知道我应该用所需的默认值替换最后一行中的Nothing,但是我仍然不知道该怎么做。查看mreqoptionsPairs签名,我的想法是在这种情况下,我应该为Maybe Option提供默认的国家/地区,但是我的尝试引发了很多类型错误,可能我很远离正确答案。

Yesod的书中使用的示例似乎比我尝试实现的示例更简单,因此我不确定如何推断它。

通过这种方式,我可以从数据库中获取默认国家/地区,因此无需对内部ID进行硬编码:

defaultCountry = do
  row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  (countryName $ entityVal row, entityKey row)

当我将其作为参数传递给mreq时,出现以下错误:

  

无法将类型“(,)文本”与“处理程序站点”匹配   预期类型:HandlerFor网站(关键记录)     实际类型:(文本,关键记录)

那是defaultContry函数((countryName $ entityVal row, entityKey row))的最后一行。我了解我应该从货币对中取出Key record并以HandlerFor site的形式返回,但同时我也得到:

  

无法匹配预期的类型“也许(关键国家/地区)”               实际类型为“ HandlerFor site0(关键记录0)”

(countryR, countryV) <- mreq (selectField countries) "" defaultCountry行中。我将其解释为“您正在向我传递HandlerFor site0 (Key record0),但我只接受Maybe (Key Country),这似乎与第一个错误...

(countryName $ entityVal row, entityKey row)行中,我还看到:

  

无法匹配预期的类型“实体国家/地区”               实际类型为“也许(实体国家/地区)”

row中的

。我了解我应该从Entity Country中提取Maybe,但是如果我进行模式匹配并仅传递Entity Country(即:Just (Entity countryId country) -> (countryName $ entityVal (Entity countryId country), entityKey (Entity countryId country)),我仍然会遇到第一个错误。 / p>

谢谢。

1 个答案:

答案 0 :(得分:1)

好的,这看起来有些类型错误。第一个

  

无法将类型“(,)文本”与“ HandlerFor site”相匹配预期类型:HandlerFor site(关键记录)实际类型:(文本,关键记录)

来自未在return表示法中使用do来将值提升为monad:

defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
  row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  return (countryName $ entityVal row, entityKey row)

row上的错误

  

无法将预期的类型“实体国家/地区”与实际类型“可能(实体国家/地区)”匹配

是因为它是Maybe,所以请更正

defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
  Just row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  return (countryName $ entityVal row, entityKey row)

现在defaultCountry是一个很好的monad,您应该可以在其他代码中使用它。但是请注意第三个错误

  

无法将预期的类型“也许(关键国家/地区)”与实际类型“ HandlerFor site0(关键记录0)”

您需要从HandlerFor单子中解包该值,然后将其重新包装到Maybe

surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
  (defaultName, defaultKey) <- defaultCountry -- (defaultName, defaultKey) :: (Text, Key record)
  (countryR, countryV) <- mreq (selectField countries) "" (Just defaultKey)