将拼接绑定到Heist中的标签

时间:2014-11-04 16:31:37

标签: haskell splice haskell-snap-framework heist

我想使用网站作为工作示例,以帮助学习Haskell。我试图关注Snap网站上的Heist tutorial,并在网页中显示因子功能的结果。

我可以定义示例函数"服务器端"没有编译器抱怨,但我无法弄清楚如何将函数绑定到一个标签,然后我可以放入HTML。具体来说,这部分工作正常(例如,Site.hs):

factSplice :: Splice Snap
factSplice = do
    input <- getParamNode
    let text = T.unpack $ X.nodeText input
        n = read text :: Int
    return [X.TextNode $ T.pack $ show $ product [1..n]]

但真正重要的部分 - 如何评估此功能作为网页的一部分(例如如何将其绑定到像&lt; fact /&gt;这样的标签) - 是神秘的。说明要放弃:

bindSplice "fact" factSplice templateState

代码中的某个地方。但仅此一点还不够。这个语句不是表达式(stuff = bindSplice ...),因此不清楚如何放在代码中。而且,它根本不清楚&#34; templateState&#34;应该来自。它几乎就像&#34; templateState&#34;应该是emptyTemplateStatedefaultHeistState等默认值的占位符,但这些似乎都在几年前已被弃用,而最新版本的Heist(0.14)无法识别它们。

MightyByte在2011年多次对这类问题进行了评论,但答案都掩盖了完全令人困惑的部分,即如何实际将数据导入网页。有人可以帮忙吗?

- 更新 -

非常感谢,mightybyte!你在源代码中的解释和一些粗略的讨论清除了很多混乱,我能够从Snap网站教程中获得阶乘的例子。这是我的解决方案 - 我是一个完整的n00b,如果解释看起来很迂腐或明显,请道歉。

我或多或少地使用了强烈建议的addConfig方法,只是从SpliceHelpers.hs复制addAuthSplices的实现。我通过&#34; snap init&#34;开始使用默认项目,并在Site.hs中定义了一个函数addMySplices

addMySplices :: HasHeist b => Snaplet (Heist b) -> Initializer b v ()
addMySplices h = addConfig h sc
    where
      sc = mempty & scInterpretedSplices .~ is
      is = do
           "fact" ## factSplice

这使用镜头访问SpliceConfig中性元素mempty的字段,因此我必须将Control.Lens添加到Site.hs中的依赖项,以及Data.Monoid以放置mempty {1}}范围内。我还将阶乘拼接的类型签名更改为factSplice :: Monad n => I.Splice n,但该函数与Heist教程中的形式相同。然后我在应用程序初始化程序中调用addMySplices,紧接在Site.hs中的addAuthSplices

app :: SnapletInit App App
...
addAuthSplices h auth
addMySplices h
...

会导致factSplice绑定到标记<fact>。正如所宣传的那样,将<fact>8</fact>删除到其中一个默认模板上会在页面上呈现40320。

大约一年前的

This question包含一个表面上类似的解决方案,但不适用于最新版本的Heist;不同之处在于,某些字段可以通过镜头而不是直接访问,这可以在Heist 0.14的Snap项目博客中解释。特别是,hcCompliedSplices已被完全重新定义 - 在Types.hs中甚至还有关于它的友好警告。

1 个答案:

答案 0 :(得分:0)

如果查看顶级海斯特模块,您会看到the initHeist function。正如文档所指出的,这是主要的初始化函数。你应该把它传递给你所有的模板和拼接。看一下类型签名告诉我们这些都是在HeistConfig数据类型中捆绑在一起的。

initHeist :: Monad n => HeistConfig n -> EitherT [String] IO (HeistState n)

这会返回一个HeistState,这是您在渲染模板时传递给renderTemplate的内容。此外,HeistConfig包含所有拼接的SpliceConfig字段。

但这是所有低级别界面。 Heist的设计与Snap无关。它是一个模板库,可以与任何Web框架一起使用。 (或者甚至是独立的,没有任何网络框架,例如生成HTML电子邮件。)如果你正在使用Heist with Snap,你可能想要使用我们提供的处理调用细节的便利东西。 initHeist,renderTemplate等

对于一个这方面的工作示例,最好的办法是查看您在执行&#34; snap init&#34;时获得的项目模板。您可以看到代码on github here。如果您查看Application.hs,您会发现应用程序数据结构中包含Heist snaplet的行。然后,如果你看the bottom of Site.hs,你就会看到他们正在调用heistInit。此函数由heist snaplet here定义。 snaplet为您负责初始化,状态管理,动态模板重新加载等。

所以,要把这一切放在一起......来自上面描述的Heist API,我们发现我们需要在HeistConfig中定义我们的拼接。但是我们的应用程序将主要通过snaplet的API与所有这些东西进行交互。因此,如果我们查看heist snaplet API涉及HeistConfig / SpliceConfig的内容,我们会发现两个相关的函数:

heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b)
addConfig :: Snaplet (Heist b) -> SpliceConfig (Handler b b) -> Initializer b v ()

这些类型签名提供了两种定义拼接的方法。您可以使用heistInit'代替heistInit并将HeistConfig传递给它。或者您可以通过调用addConfig生成Snaplet (Heist b)来添加拼接。