我爱编程

「blaze-html」Day 1. - 30天Hackage之

2016-11-11  本文已影响45人  kdepp

30天Hackage之旅,第一天献给 blaze-html 这个『贼快』(blazing fast) 的 HTML combinator。

示例

blaze-html 让我们可以用类似前端里 pug 的语法来写 HTML,HTML代码的层级关系通过 do 表达得非常清楚,同时属性的书写也通过 (!) 得到了很好的支持

{-# LANGUAGE OverloadedStrings #-}

import Text.Blaze.Html5 as H5 hiding (main)
import Text.Blaze.Html5.Attributes as A
import Text.Blaze.Html.Renderer.Utf8 (renderHtml)

main :: IO ()
main = print $ renderHtml demo

demo = docTypeHtml $ do
    H5.head $ do
        H5.title "Natural numbers"
    body $ do
        p "A list of natural numbers:"
        img ! src "foo.png" ! alt "A foo image."

输入为:

<!DOCTYPE HTML>
<html><head><title>Natural numbers</title></head><body><p>A list of natural numbers:</p><img src="foo.png" alt="A foo image."></body></html>"

解读

blaze-html 最大的特色,就是用简洁的语法表达了 Html 元素之间的组合关系。其中,又以 do 语法糖的使用最为精彩和诡异,而整体实现方式又相对简单易懂。接下来,我们就来打开 blaze-html 的代码,看看这种简洁是怎么做到的:

问题

在我们肯定 blaze-html 提供的简洁性的同时,我们也需要注意,虽然 Html>> 和对应的 do 语法糖很好用,但其实这样的定义并不能算是真正的 Monad, 因为这违反了 Monad Laws

Left identity:  return a >>= f  ≡    f a
Right identity: m >>= return    ≡    m
Associativity:  (m >>= f) >>= g ≡    m >>= (\x -> f x >>= g)

实际上,HtmlMonad 实例不满足以上任意一条。这样的结果是,没有办法定义 Monad transformer HtmlT ,所以也就没有办法和其他 Monad 混合使用。比如,理想实现下,我们可以用包一层 ReaderT 来实现模板变量的功能

应用

作为一个高效的 Html combinator 函数库,blaze-html 的应用面还是很广的。比如,ShakespeareHamlet 模板,就使用了 blaze-html 的 Html 类型作为自己的最终输出。

上一篇下一篇

猜你喜欢

热点阅读