我应该如何使用runDB函数创建一个selectFieldList来获取值?

时间:2015-04-08 11:42:48

标签: haskell yesod yesod-forms

我想在我的表单中添加一个selectionFieldList,但不幸的是我无法填充DB的值,因为我遇到了编译错误。

我有这样的表单定义:

flowerForm = renderDivs $ FormFlower
<$> areq textField "Flower" Nothing
<*> areq (selectFieldList findAllAsTuple) "Category" Nothing

findAllAsTuple函数:

findAllAsTuple ::[(Text,Text)]
findAllAsTuple = fmap (map (\cat -> (categoryName $ entityVal cat, categoryName $ entityVal cat))) $ runDB $ selectList [] [Asc CategoryName]

但我收到了这个错误:

Handler\Category.hs:6:18:
Couldn't match type `HandlerT site0 IO' with `[]'
Expected type: [(Text, Text)]
  Actual type: HandlerT site0 IO [(Text, Text)]
In the expression:
  fmap
    (map
       (\ cat
          -> (categoryName $ entityVal cat, categoryName $ entityVal cat)))
  $ runDB $ selectList [] [Asc CategoryName]
In an equation for `findAllAsTuple':
    findAllAsTuple
      = fmap
          (map
             (\ cat
                -> (categoryName $ entityVal cat, categoryName $ entityVal cat)))
        $ runDB $ selectList [] [Asc CategoryName]

如果删除fmap,我收到此错误:

Handler\Category.hs:6:95:
Couldn't match expected type `[Entity Category]'
            with actual type `HandlerT site0 IO [Entity Category]'
In the second argument of `($)', namely
  `runDB $ selectList [] [Asc CategoryName]'
In the expression:
  map
    (\ cat
       -> (categoryName $ entityVal cat, categoryName $ entityVal cat))
  $ runDB $ selectList [] [Asc CategoryName]
In an equation for `findAllAsTuple':
    findAllAsTuple
      = map
          (\ cat
             -> (categoryName $ entityVal cat, categoryName $ entityVal cat))
        $ runDB $ selectList [] [Asc CategoryName]

我也尝试过这种方式:

findAllAsTuple ::[(Text,Text)]
findAllAsTuple = do
            items <-  runDB $ selectList [] [Asc CategoryName]
            return $ map (\cat -> (categoryName $ entityVal cat,      categoryName $ entityVal cat))  items

但我得到了这个:

Handler\Category.hs:8:17:
Couldn't match type `[(Text, Text)]' with `(Text, Text)'
Expected type: [(Text, Text)]
  Actual type: [[(Text, Text)]]
In a stmt of a 'do' block:
  return
  $ map
      (\ cat
         -> (categoryName $ entityVal cat, categoryName $ entityVal cat))
      items
In the expression:
  do { items <- runDB $ selectList [] [Asc CategoryName];
       return
       $ map
           (\ cat
              -> (categoryName $ entityVal cat, categoryName $ entityVal cat))
           items }
In an equation for `findAllAsTuple':
    findAllAsTuple
      = do { items <- runDB $ selectList [] [Asc CategoryName];
             return
             $ map
                 (\ cat
                    -> (categoryName $ entityVal cat, categoryName $ entityVal cat))
                 items }

我不明白为什么。如果我写这样一个简单的地图函数:

 findAllAsTuple ::[(Text,Text)]
 findAllAsTuple =  map (\cat -> (cat,cat))  ["red","blue","yellow"]

效果很好,我没有任何类型错误。

2 个答案:

答案 0 :(得分:2)

findAllAsTuple的类型为HandlerT site IO [(Text, Text)]。 您可以通过删除(错误的)类型签名在GHCI中进行检查。

函数selectFieldList应该在没有任何IO的情况下从静态列表中获取数据。

最好的方法是使用函数selectField。你应该看看它的类型: selectField ::(Eq a, RenderMessage site FormMessage) => HandlerT site IO (OptionList a) -> Field (HandlerT site IO) a

即。你可以用类似的东西 selectList (fmap convertYourListToOptionList findAllAsTuple)

答案 1 :(得分:0)

最后我找到了解决方案。

我的功能应如下所示:

findAllAsTuple :: HandlerT App IO (OptionList Text)
findAllAsTuple =do 
             items <- runDB $ selectList [] [Asc CategoryName] 
             optionsPairs $ map (\c -> (categoryName $ entityVal    c,categoryName $ entityVal c)) items

Dmitry是对的我应该使用selectField而不是selectFieldList。

optionsPairs将从结果中创建OptionList。 这个问题很复杂:Capturing Persistent Relations in a Form