我对Yesod很陌生,似乎完全迷上了小部件、处理程序、哈姆雷特、WHamlets等等!我想做的是:
defaultLayout。因此,我尝试用Foundation.hs编写以下函数(代码布局是基本的yesod-sqlite脚手架模板):
nav = do
globalStat <- handlerToWidget $ A2.getGlobalStat NWT.ariaRPCUrl
$(whamletFile "templates/navbar.hamlet)
A2.getGlobalStat :: IO GlobalStatResponse下面是template/navbar.hamlet的样子:
<nav .navbar .navbar-default>
<div .container-fluid>
<p .navbar-right .navbar-text>
<span>
#{A2.glDownloadSpeed globalStat}
<i .glyphicon .glyphicon-arrow-down>
<span>
#{A2.glUploadSpeed globalStat}
<i .glyphicon .glyphicon-arrow-up>
<span .label .label-success>
On-the-watch下面是default-layout-wrapper.hamlet的样子:
<!-- SNIP -->
<body>
<div class="container">
<header>
^{nav}
<div id="main" role="main">
^{pageBody pc}
<!-- SNIP -->下面是defaultLayout的样子:
defaultLayout widget = do
master <- getYesod
mmsg <- getMessage
pc <- widgetToPageContent $ do
addStylesheet $ StaticR css_bootstrap_css
$(widgetFile "default-layout")
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")但是,代码拒绝使用一个又一个类型错误进行编译.我尝试了很多hametFile、whamletFile、handerToWidget、liftIO的组合,甚至把nav函数放在defaultLayout中,但是似乎没有什么效果。据我所知,我当前的代码应该编译,但我显然不明白Yesod-Core类型是如何工作的。
我怎么才能让这个起作用?更重要的是,我误解了什么概念?
编辑1:
尝试将nav函数修改为:
nav :: Handler Html
nav = do
globalStat <- liftIO $ A2.getGlobalStat NWT.ariaRPCUrl
$(hamletFile "templates/navbar.hamlet")但是,这会导致defaultLayout中与withUrlRenderer的类型不匹配
Couldn't match type ‘HandlerT App IO Html’
with ‘Text.Hamlet.Render (Route App) -> Html’
Expected type: HtmlUrl (Route App)
Actual type: Handler Html
In the first argument of ‘Text.Hamlet.asHtmlUrl’, namely ‘nav’
In a stmt of a 'do' block: Text.Hamlet.asHtmlUrl nav _render_a2ZY0 (intero)编辑2:
尝试将nav的类型签名更改为:
nav :: Widget
nav = do
globalStat <- liftIO $ A2.getGlobalStat NWT.ariaRPCUrl
$(hamletFile "templates/navbar.hamlet") 但它导致了一种新的类型错配,同一行:
Couldn't match type ‘WidgetT App IO ()’
with ‘Text.Hamlet.Render (Route App) -> Html’
Expected type: HtmlUrl (Route App)
Actual type: Widget
In the first argument of ‘Text.Hamlet.asHtmlUrl’, namely ‘nav’
In a stmt of a 'do' block: Text.Hamlet.asHtmlUrl nav _render_a350l (intero)编辑3:
以下是来自-ddump-splices的相关片段
\ _render_a28TE
-> do { asHtmlUrl (pageHead pc) _render_a28TE;
id ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\n");
asHtmlUrl (pageBody pc) _render_a28TE;
id ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\n");
asHtmlUrl testWidget2 _render_a28TE }(pageHead pc)和(pageBody pc)的类型是HtmlUrl (Route App)
发布于 2016-07-10 13:15:41
看看这个问题的答案。基本上,您不能在模板中执行IO。
还请注意,defaultLayout的类型是GHandler ...,GHandler是MonadIO实例,因此可以使用liftIO在defaultLayout中执行IO。
我试着:
defaultLayout = do
...
globalStat <- liftIO $ handlerToWidget $ A2.getGlobalStat NWT.ariaRPCUrl
uploadSpeed <- liftIO $ A2.glUploadSpeed globalStat
downloadSpeed <- liftIO $ A2.glDownloadSpeed globalStat
...
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")在templates/default-layout-wrapper.hamlet中
...
^{nav uploadSpeed downloadSpeed}
...而nav变成了这样的东西:
nav uploadSpeed downloadSpeed = $(whamletFile "templates/navbar.hamlet)因此,基本的想法是:
defaultLayout中使用liftIO执行所有IO操作更新
要模仿Yesod书中的例子,您需要像这样编写navbar:
navbar :: Widget
navbar = do
globalStat <- liftIO A2.getGlobalStat NWT.ariaRPCUrl
downloadSpeed <- liftIO A2.glDownloadSpeed globalStat
uploadSpeed <- liftIO A.glUploadSpeed
$(whamletFile "templates/navbar.hamlet)在navbar.whamlet中,指#{uploadSpeed}和#{downloadSpeed}。
你不能在文件里做IO。而且,您的A2函数是IO操作,但是handlerToWidget需要一个HandlerT操作,所以您需要使用liftIO来转换这些调用。
更新2
有关在Widget中执行IO的工作示例,请参见http://lpaste.net/169497。
发布于 2016-07-11 12:27:11
这是我怎么让它工作的。实际上,我面临着两个不同的问题:
default-layout-wrapper hamletFile中的Widget。下面是在小部件中执行IO的解决方案:
nav :: Widget
nav = do
globalStat <- liftIO $ A2.getGlobalStat NWT.ariaRPCUrl
$(whamletFile "templates/navbar.hamlet")注意:类型签名nav :: Widget似乎是必要的,否则类型推理引擎可能会混淆,并为liftIO操作推断出一种非常不同的类型(最初发生在我身上)。
对于第二个问题,我无法真正找到在default-layout-wrapper hamletFile中引用Widget的解决方案。当呈现这个特定的hamletFile时,Widget已经转换为PageContent类型,现在它需要一个Html url类型才能与withUrlRenderer函数一起呈现它。基本上,我无法让Widget和PageContent来作曲。然而,以下方法以不同的方式给了我想要的结果:
default-layout.hamlet:在这个文件中添加了对nav小部件的调用。将一些元素从default-layout-wrapper移到这个文件中:
<div .container>
<header>
^{nav}
<div #main role="main">
$maybe msg <- mmsg
<div #message>#{msg}
^{widget}default-layout-wrapper.hamlet:将一些HTML元素从这个文件移到了default-layout
<!-- SNIP -->
<body>
<div class="container">
^{pageBody pc}
<!-- SNIP -->https://stackoverflow.com/questions/38289927
复制相似问题