0
votes

I have a Yesod handler that is returning a list of type [(Category, [Product])] I am trying to loop through this in my hamlet template.

$if null rows
    <p>No products
$else
  <div class="list-group menu">
    $forall (category, products) <- rows
      <h4>#{categoryName category}

      $forall product <- products
        <p>#{productName product} - #{productPrice product}</p>

When I compile though I get the error message:

Handler/Menu.hs:11:7:
    Couldn't match type ‘[(Category, [Product])]’
                   with ‘(Category, t0 Product)’
    Expected type: ReaderT SqlBackend m1 (Category, t0 Product)
      Actual type: ReaderT SqlBackend m1 [(Category, [Product])]
    In the second argument of ‘Data.Foldable.mapM_’, namely ‘rows’
    In a stmt of a 'do' block:
      Data.Foldable.mapM_
        (\ (category_aiv7, products_aiv8)
           -> do { (asWidgetT GHC.Base.. toWidget)
                     ((blaze-markup-0.7.0.3:Text.Blaze.Internal.preEscapedText
                       GHC.Base.. Data.Text.pack)
                        "<div class=\"list-group-item\"><h4 class=\"list-group-item-heading\">");
                   (asWidgetT GHC.Base.. toWidget)
                     (toHtml (categoryName category_aiv7));
                   .... })
        rows

I don't understand why it is expecting this and what I can do to make it work. Many Thanks.

Update: My handler.

getMenuR :: Handler Html
getMenuR = do
  let rows = query

  defaultLayout $ do
    $(widgetFile "menu")

query = do
  cats <- selectList [] [Asc CategoryName]
  forM cats $ \(Entity catId cat) -> do
      products <- selectList
          [ProductCategory ==. catId]
          [Asc ProductName]
      return (cat, map entityVal products)
1
I think the problem is in your Haskell code. What does the code that created rows look like? - Michael Snoyman
Hi Michael, It was the code that you helped with the other day. I have added it to the question. Thanks Again. - Stewart Webb
The problem is using a let binding. You should use the slurp operator instead (<-). - Michael Snoyman
Hi, so I changed from let rows = query to rows <- query and now I am getting this error: Handler/Menu.hs:8:11: Couldn't match expected type ‘HandlerT App IO (t0 (Category, t1 Product))’ with actual type ‘ReaderT SqlBackend m0 [(Category, [Product])]’ - Stewart Webb
You need runDb. I'd recommend looking more closely as the Yesod/persistent examples in the book - Michael Snoyman

1 Answers

0
votes

After the help from Michael it is as easy as replacing let rows = query with rows <- runDB query