繁体   English   中英

绑定拼接以在Heist中进行标记

[英]Bind splice to tag in Heist

我想使用一个网站作为工作示例,以帮助学习Haskell。 我正在尝试遵循Snap网站上的Heist教程 ,并在网页中显示阶乘函数的结果。

我可以在没有编译器抱怨的情况下获得在服务器端定义的示例函数,但是我无法弄清楚如何将函数绑定到标签上,然后将其放入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]]

但是,真正重要的部分-如何将其作为网页的一部分进行评估(例如如何将其绑定到<fact />之类的标签上)-很神秘。 说明删除:

bindSplice "fact" factSplice templateState

代码中的某处。 但是,仅此一项是不够的。 该语句不是表达式(stuff = bindSplice ...),因此不清楚如何代码中放置它。 而且,还不清楚“ templateState”应该从哪里来。 几乎好像“ templateState”应该是emptyTemplateState的占位符,例如emptyTemplateStatedefaultHeistState ,但是它们似乎都在多年前就已弃用,并且最新版本的Heist(0.14)无法识别它们。

MightyByte在2011年曾多次对此类问题发表评论,但答案完全掩盖了令人困惑的部分,即如何实际将数据获取到网页中。 有人可以帮忙吗?

-更新-

非常感谢,mayybyte! 您的解释和对源代码的一些粗略的查找消除了很多混乱,并且我能够从Snap网站教程的工作中获得析因示例。 这是我的解决方案-我是一个完整的n00b,因此,如果解释似乎过于古怪或显而易见,则深表歉意。

我或多或少使用了mayybyte建议的addConfig方法,只是从SpliceHelpers.hs复制addAuthSplices的实现。 我通过“ snap init”从默认项目开始,并在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放在范围内。 我还将阶乘剪接的类型签名更改为factSplice :: Monad n => I.Splice n ,但该功能在Heist教程中的形式没有变化。 然后我把电话给addMySplices在应用程序初始化,毗邻addAuthSplices在Site.hs

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

这实际上导致将factSplice绑定到标签<fact> 如广告中所示,将<fact>8</fact>放到默认模板之一中会在页面上呈现40320。

大约一年前的这个问题包含了一个表面上类似的解决方案,但不适用于最新版本的Heist。 区别在于某些字段是通过镜头而不是直接访问的,这在Snap项目博客中发布了Heist 0.14进行了说明。 特别是, hcCompliedSplices已被完全重新定义hcCompliedSplices中甚至hcCompliedSplices有一个友好的警告。

如果您查看顶级Heist模块,则会看到initHeist函数 正如文档指出的那样,这是主要的初始化功能。 而且您应该将所有模板和接头都传递给它。 查看类型签名可以了解到,这些都捆绑在HeistConfig数据类型中。

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

这会给您带来HeistState,这是您要呈现模板时传递给renderTemplate 另外,HeistConfig包含所有接头的SpliceConfig字段。

但这就是所有低级接口。 Heist设计为不依赖Snap。 它是一个模板库,可以与任何Web框架一起使用。 (或者甚至根本没有用于生成HTML电子邮件之类的任何Web框架的独立框架。)如果您将Heist与Snap结合使用,则可能需要使用我们提供的便捷工具,来处理调用initHeist,renderTemplate,等等

对于一个可行的示例,最好的选择是查看执行“ snap init”时获得的项目模板。 您可以在github上看到该代码。 如果查看Application.hs ,则会看到在应用程序数据结构中有一行包含Heist snaplet的行。 然后,如果您查看Site.hs的底部 ,则会看到有对heistInit的调用。 此功能由此处的抢劫小扣定义。 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 heistInit传递给它。 或者,您也可以通过使用结果Snaplet (Heist b)调用addConfig Snaplet (Heist b)来添加接头。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM