Lucid的“术语”类型的真实含义

时间:2019-11-03 22:56:09

标签: html haskell bootstrap-4 haskell-lucid

我一直在与Haskell合作,尝试使用Servant和Lucid创建一个非常简单的网站。目前,我到达“我的代码有效,我不知道为什么”的阶段。 我尝试创建Bootstrap按钮。根据文档,应将其定义为:

<button type="button" class="btn btn-primary">Primary</button>

因此,我找到了Lucid.Html5文档:https://hackage.haskell.org/package/lucid-2.9.11/docs/Lucid-Html5.html,并得出了创建按钮的功能:

button_ :: Term arg result => arg -> result

花了一些时间试图找出正确的语法后,我想到了:

-- correctly replicates the html pasted above
button_ [type_ "button", class_ "btn btn-primary"] "Primary"

通常我会称其为胜利,并专注于其他任务,但这对我来说似乎是一件真正的魔术。

文档说“ button_”是一个接受参数“ arg”并返回通用类型“ result”的值的函数。但是,在我的应用程序中,“ button_”显然带有两个参数并返回“ Html()”。

-- f                       arg                     arg again ??
button_ [type_ "button", class_ "btn btn-primary"] "Primary"

它必须对“ Term”类型类进行某些操作,但是我不确定如何理解它。有人可以帮我弄这个吗 ?我尝试将模块加载到ghci中并使用“:t”检查类型,但这并没有太大帮助。

1 个答案:

答案 0 :(得分:4)

Term类型类非常方便-我们不需要不同的term函数来创建带有或不带有属性的元素-但可能有点难以理解。

button_的定义是

-- | @button@ element
button_ :: Term arg result => arg -> result
button_ = term "button"

termTerm类型类的方法,其类型为:

term :: Text -> arg -> result   

也就是说,您给它提供元素的名称,一些其类型取决于特定实例的参数,并返回一些其类型取决于特定实例的结果。但是哪些实例可用?有三个:

Term Text Attribute
-- here, term :: Text -> Text -> Attribute

这是用于创建属性而不是元素的

Applicative m => Term (HtmlT m a) (HtmlT m a)
-- here, term :: Text -> HtmlT m a -> HtmlT m a

这是用于创建没有属性的元素的。我们作为参数传递给arg的{​​{1}}是代表孩子的html片段,作为回报,我们得到了另一段html。

term

这是最令人困惑的,也是代码中正在使用的那个。这里,(Applicative m, f ~ HtmlT m a) => Term [Attribute] (f -> HtmlT m a) -- here, term :: Text -> [Attribute] -> HtmlT m a -> HtmlT m a Attribute值的列表。那很清楚。但是arg是函数的类型!传递属性后,我们剩下的是另一个函数result-> HtmlT m a,该函数使我们能够提供按钮的内容(在您的情况下为“主要”)。 / p>

HtmlT m a是另一个皱纹,与该答案无关。它只是说f ~ HtmlT m a等于f。那为什么不直接放呢?好吧,在某些情况下,它可以以理想的方式帮助drive type inference