jovanKg
jovanKg

Reputation: 45

Problem to show value out of Handler monad in Haskell and Yesod

I am a beginner in Haskell and I am still studying and I stopped at the problem that has to do with monads.
The problem is that I want to show the comment writer in the template.
I can't do that because when I add a comment from the database it is always in the Handler monad.
Maybe my whole idea is wrong I don't know.

This is the comment entity:

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

This is the handler function:

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

Part of hamlet file (in last line trying to show writer):

$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> 

I'm trying to get a comment writer here:

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

Eventually an error occurred:

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

Upvotes: 1

Views: 124

Answers (1)

Random Dev
Random Dev

Reputation: 52280

you should be able to use it in the same way you use comments there: bind it to a local value and access this in your hamlet-file/code.

Of course you want to pair this up with the comment itself so I'd propose something like this:


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>

Of course you should look into querying both of this together if you can but basically this should work.


PS: if you want to use more fields you probably would want to use a record - here I choose to tuple it up for simplicity.

Upvotes: 2

Related Questions