清醒"Term"型的真正含义



我一直在玩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"

它一定与"术语"类型类有关,但我不知道如何理解它。有人能帮我吗?我试着将模块加载到ghci中,并用":t"检查类型,但这对我没有太大帮助。

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

这个用于创建没有属性的元素。我们作为参数传递给termarg是表示子级的一段html,作为回报,我们得到另一段html。

(Applicative m, f ~ HtmlT m a) => Term [Attribute] (f -> HtmlT m a)
-- here, term :: Text -> [Attribute] -> HtmlT m a -> HtmlT m a

这一个是最令人困惑的,也是您的代码中正在使用的一个。这里,argAttribute值的列表。这一点很清楚。但是result是函数的类型!传递属性后,我们剩下另一个函数HtmlT m a->HtmlT m a,它允许我们提供按钮的内容(在您的情况下为"主要"(。

f ~ HtmlT m a是另一个与这个答案并不相关的问题。它简单地说f等于HtmlT m a。那为什么不直接说呢?在某些情况下,它可以帮助以理想的方式驱动类型推理。

相关内容

  • 没有找到相关文章

最新更新