{-# LANGUAGE TypeFamilies, QuasiQuotes, TemplateHaskell, MultiParamTypeClasses, OverloadedStrings #-}
import Yesod
data Entry = Entry
{ entryTitle :: String
, entrySlug :: String -- ^ used in the URL
, entryContent :: String
}
loadEntries :: IO [Entry]
loadEntries = return
[ Entry "Entry 1" "entry-1" "My first entry"
, Entry "Entry 2" "entry-2" "My second entry"
, Entry "Entry 3" "entry-3" "My third entry"
]
data Blog = Blog { blogEntries :: [Entry] }
type Handler = GHandler Blog Blog
mkYesod "Blog" [parseRoutes|
/ HomeR GET
/entry/#String EntryR GET
|]
instance Yesod Blog where approot _ = ""
getHomeR :: Handler ()
getHomeR = do
Blog entries <- getYesod
let newest = last entries
redirect RedirectTemporary $ EntryR $ entrySlug newest
data TemplateArgs = TemplateArgs
{ templateTitle :: Html
, templateContent :: Html
, templateNavbar :: [Nav]
}
data Nav = Nav
{ navUrl :: Route Blog
, navTitle :: Html
}
entryTemplate :: TemplateArgs -> Hamlet (Route Blog)
entryTemplate args = [hamlet|
!!!
<html>
<head>
<title>#{templateTitle args}
<body>
<h1>Yesod Sample Blog
<h2>#{templateTitle args}
<ul id="nav">
$forall nav <- templateNavbar args
<li>
<a href="@{navUrl nav}">#{navTitle nav}
<div id="content">
\#{templateContent args}
|]
getEntryR :: String -> Handler RepHtml
getEntryR slug = do
Blog entries <- getYesod
case filter (\e -> entrySlug e == slug) entries of
[] -> notFound
(entry:_) -> do
let nav = reverse $ map toNav entries
let tempArgs = TemplateArgs
{ templateTitle = toHtml $ entryTitle entry
, templateContent = toHtml $ entryContent entry
, templateNavbar = nav
}
hamletToRepHtml $ entryTemplate tempArgs
where
toNav :: Entry -> Nav
toNav e = Nav
{ navUrl = EntryR $ entrySlug e
, navTitle = toHtml $ entryTitle e
}
main :: IO ()
main = do
entries <- loadEntries
warpDebug 3000 $ Blog entries
$ runghc Blog.hs
Blog.hs:21:1:
Multiple declarations of `Handler'
Declared at: Blog.hs:19:6
Blog.hs:21:1
答案 0 :(得分:1)
最新的Yesod现在自动声明Handler类型别名。只需删除type Handler = ...
行即可。我会更新这本书,我想我的检查脚本还没有处理Literate Haskell代码。