I am trying to get the blog example to run, but there is a problem with types in some handler functions and I don't know how to fix it.
The example I am trying to run is posted here: Yesod blog example I changed a little bit of it, I added types to defaultLayout function and made it an instance of Yesod to get rid of double definitions.
defLayout :: GWidget a Blog () -> GHandler a Blog RepHtml
defLayout inside = do
mmsg <- getMessage
pc <- widgetToPageContent $ do
toWidget [lucius|
body {
width: 760px;
margin: 1em auto;
font-family: sans-serif;
}
textarea {
width: 400px;
height: 200px;
}
#message {
color: #900;
}
|]
inside
hamletToRepHtml [hamlet|
$doctype 5
<html>
<head>
<title>#{pageTitle pc}
^{pageHead pc}
<body>
$maybe msg <- mmsg
<div #message>#{msg}
^{pageBody pc}
|]
instance Yesod Blog where
approot = ApprootStatic "http://localhost:3000"
defaultLayout = defLayout
These are the functions that give me problems:
getBlogR :: Handler RepHtml
getBlogR = do
muser <- maybeAuth
entries <- runDB $ selectList [] [Desc EntryPosted]
((_, entryWidget), enctype) <- generateFormPost entryForm
defaultLayout $ do
setTitleI MsgBlogArchiveTitle
[whamlet|
$if null entries
<p>_{MsgNoEntries}
$else
<ul>
$forall Entity entryId entry <- entries
<li>
<a href=@{EntryR entryId}>#{entryTitle entry}
$maybe Entity _ user <- muser
$if isAdmin user
<form method=post enctype=#{enctype}>
^{entryWidget}
<div>
<input type=submit value=_{MsgNewEntry}>
$nothing
<p>
<a href=@{AuthR LoginR}>_{MsgLoginToPost}
|]
getEntryR :: EntryId -> Handler RepHtml
getEntryR entryId = do
(entry, comments) <- runDB $ do
entry <- get404 entryId
comments <- selectList [] [Asc CommentPosted]
return (entry, map entityVal comments)
muser <- maybeAuth
((_, commentWidget), enctype) <- generateFormPost (commentForm entryId)
defaultLayout $ do
setTitleI $ MsgEntryTitle $ entryTitle entry
[whamlet|
<h1>#{entryTitle entry}
<article>#{entryContent entry}
<section .comments>
<h1>_{MsgCommentsHeading}
$if null comments
<p>_{MsgNoComments}
$else
$forall Comment _entry posted _user name text <- comments
<div .comment>
<span .by>#{name}
<span .at>#{show posted}
<div .content>#{text}
<section>
<h1>_{MsgAddCommentHeading}
$maybe _ <- muser
<form method=post enctype=#{enctype}>
^{commentWidget}
<div>
<input type=submit value=_{MsgAddCommentButton}>
$nothing
<p>
<a href=@{AuthR LoginR}>_{MsgLoginToComment}
|]
Here is the output I get when I try to run it:
blog.hs:147:4:
Couldn't match expected type `GWidget Blog Blog ()'
with actual type `(t0, t1)'
In the pattern: (_, entryWidget)
In the pattern: ((_, entryWidget), enctype)
In a stmt of a 'do' block:
((_, entryWidget), enctype) <- generateFormPost entryForm
blog.hs:202:4:
Couldn't match expected type `GWidget Blog Blog ()'
with actual type `(t0, t1)'
In the pattern: (_, commentWidget)
In the pattern: ((_, commentWidget), enctype)
In a stmt of a 'do' block:
((_, commentWidget), enctype) <- generateFormPost
(commentForm entryId)
The type of generateFormPost
has changed since the blog article, it used to be
generateFormPost :: RenderMessage master FormMessage =>
(Html -> MForm sub master (FormResult a, xml)) ->
GHandler sub master ((FormResult a, xml), Enctype)
in yesod-form-0.4.* but now it is
generateFormPost :: RenderMessage master FormMessage =>
(Markup -> MForm sub master (FormResult a, xml)) ->
GHandler sub master (xml, Enctype)
The type error should [I think, never used yesod] go away if you use yesod-form < 1
, or if you replace
((_, entryWidget), enctype) <- generateFormPost entryForm
with
(entryWidget, enctype) <- generateFormPost entryForm
to reflect the change in the type of generateFormPost
.