【问题标题】:Problem to show value out of Handler monad in Haskell and Yesod在 Haskell 和 Yesod 中显示 Handler monad 价值的问题
【发布时间】:2021-08-22 22:31:00
【问题描述】:

我是 Haskell 的初学者,我还在学习,我在与 monad 相关的问题上停了下来。
问题是我想在模板中显示评论作者。
我不能这样做,因为当我从数据库添加评论时,它总是在 Handler monad 中。
也许我的整个想法是错误的,我不知道。

这是评论实体:

ManComment
text Text sqltype=varchar(500)
created UTCTime sqltype=DateTime
writer UserId Maybe sqltype=varchar(255) default=NULL  -- comment writer
manId ManifestationId sqltype=varchar(255) default=NULL
deriving Show Typeable

这是处理函数:

getManDetailsR :: ManifestationId -> Handler Html
getManDetailsR mid = do 
  (ui, user) <- requireAuthPair
  comments <- runDB $ getComFromMan mid
  defaultLayout $ do
     setTitle "Manifestation details"
     $(widgetFile "man-details")

哈姆雷特文件的一部分(在最后一行试图显示作者):

$if null comments 
  <h4>There is not comments! 
$else 
  $forall Entity cid com <- comments 
    <form method=post action=@{DeleteManCommentR mid cid}> 
      <li .list-group-item> 
        <div class="row"> 
         <div class="col-xs-10 col-md-11"> 
         <div> 
          <div .mic-info> By: <a href=@{ProfileR}>#{getCommentWriter $ com}</a> 

我正在尝试在这里获得评论作者:

getCommentWriter :: ManComment -> Handler Text
getCommentWriter c = do 
  user <- runDB $ get404 $ fromJust $ manCommentWriter c  --get writer from database
  let username = userIdent user 
  return username  -- but return puts in Handler monad

最终发生错误:

No instance for (blaze-markup-0.8.2.7:Text.Blaze.ToMarkup
                         (Handler Text))
        arising from a use of ‘toHtml’ 

【问题讨论】:

    标签: haskell monads yesod


    【解决方案1】:

    您应该能够以与您在那里使用comments 相同的方式使用它:将其绑定到本地值并在您的 hamlet-file/code 中访问它。

    当然你想把它和评论本身配对,所以我建议这样:

    
    getCommentAndWriter :: ManComment -> Handler (Entity ManComment, Text)
    getCommentAndWriter c = do 
      user <- runDB $ get404 $ fromJust $ manCommentWriter c  --get writer from database
      let username = userIdent user 
      return (c, username)
    
    getManDetailsR :: ManifestationId -> Handler Html
    getManDetailsR mid = do 
      (ui, user) <- requireAuthPair
    
      cs <- runDB $ getComFromMan mid
      comments <- forM cs getCommentAndWriter
      
      defaultLayout $ do
         setTitle "Manifestation details"
         $(widgetFile "man-details")
    
    $if null comments 
      <h4>There is not comments! 
    $else 
      $forall (Entity cid com, writer) <- comments 
        <form method=post action=@{DeleteManCommentR mid cid}> 
          <li .list-group-item> 
            <div class="row"> 
             <div class="col-xs-10 col-md-11"> 
             <div> 
              <div .mic-info> By: <a href=@{ProfileR}>#{writer}</a>
    

    当然,如果可以的话,您应该考虑同时查询这两者,但基本上这应该可以工作。


    PS:如果您想使用更多字段,您可能会想要使用一条记录 - 为了简单起见,我选择将其组合起来。

    【讨论】:

    • 非常感谢您尝试回答我并帮助@Carsten。我喜欢这个解决方案,我正在尝试使用它。现在的问题是“cs”列表是 [Entity ManComment],而不仅仅是 [ManComment],我得到一个错误:Couldn't match type ‘(ManComment, Text)’ with ‘()’Expected type: Element [Entity ManComment] -&gt; HandlerFor App ()Actual type: ManComment -&gt; Handler (ManComment, Text)
    • 我设法解决了它。我更改了函数的签名,现在它是:getCommentWriter :: Entity ManComment -&gt; Handler (Entity ManComment, Text) 而不是 forM_(它不返回结果)我使用 forM。再次非常感谢。
    • 是的,很抱歉没有注意到这一点 - 很高兴你能解决它(我会更新答案,这样其他人就不会怀疑了)
    猜你喜欢
    • 2018-04-27
    • 2021-09-21
    • 2023-02-26
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多