Yesod hamlet循环按类别细分

时间:2015-10-25 00:25:26

标签: haskell yesod hamlet

我正在尝试遍历hamlet中的每个产品都有一个类别的产品列表。我想将输出细分为分类,并在每个类别标题下面列出产品列表。有没有办法在循环我的产品时在哈姆雷特做这件事。我目前在下面显示的是每个产品的标题。我想我可能会犯这个错误。

$if null products
  <p>No products
$else
  <div class="list-group menu">
    $forall product <- products
      <div class="list-group-item">
        <h4 class="list-group-item-heading">#{categoryName $snd product}

      <div class="list-group-item">
        <div class="container-fluid">
          <div class="col-md-12">
            <p>#{productName $fst product} - #{productPrice $fst product}

以下是从[(Product Category)]

类型的数据库中获取产品的代码
products <- runDB $ selectList [ProductName !=. ""] [LimitTo 10] >>= mapM (\qe@(Entity _ q) -> do
    Just category <- get $ productCategory q
    return (q, category))

1 个答案:

答案 0 :(得分:4)

我认为答案是让您的yesod控制器将产品分组为您。

例如,而不是导出:

products :: [Product]

出口:

productGroups :: [ (Category, [Product]) ]

然后你的模板代码如下:

$if null productGroups
  <p>No products.
$else
  <div ...>
    $forall (category, products) <- productGroups
      <h4>#{category}</h4>
      $forall product <- products
        <div>...render the product...</div>

这样,产品会根据其类别显示在组中。

要创建产品组,您可以使用以下内容:

import GHC.Exts (groupWith)

groupByCategory :: [Product] -> [ (Category, [Product]) ]
groupByCategory ps =  [ (getCategory (head g), g) | g <- groupWith getCategory ]
  where getCategory product = categoryName (snd product)

警告:这是未经测试的未经验证的代码。

<强>更新

回答你在评论中提出的问题,这是一种按第二个坐标分组对列表的方法:

import Data.Ord (comparing)
import Data.List (sortBy, groupBy)

groupBySecond :: Ord b => [ (a,b) ] -> [ (b, [a]) ]
groupBySecond pairs =
  let sorted = sortBy (comparing snd) pairs 
      groups = groupBy (\(a1,b1) (a2,b2) -> b1 == b2) sorted 
      result = [ (snd (head g), map fst g) | g <- groups ]
  in result