0

我目前正在用 Lucid 重写一个 HTML 文件,以便与 Spock Web 服务器一起使用。但是,由于某种原因,这个特定的片段给了我一个错误:

sidebar :: Html ()
sidebar = do
  nav_ [id_ "sidebar"] $ do
    div [class_ "sidebar-header"] $
      h3_ "Sidebar"

    div [class_ "list-group"] $ do
      a_ [href_ "#", class_ "menuItem list-group-item rounded-0"] "Item 1"
      a_ [href_ "#", class_ "menuItem list-group-item rounded-0"] "Item 2"

即,错误是:

Couldn't match type `[Attribute]'
               with `HtmlT Data.Functor.Identity.Identity ()'
  arising from a use of `nav_'

我注意到删除 div 并h3解决问题,但这不是我想要的。我进行了一些谷歌搜索以尝试找到问题,但从我所见,图书馆并没有那么多我可以尝试查看的在线示例。Stackoverflow 和 Reddit 搜索也没有发现任何内容。

这是我使用 Lucid 的第一个实际项目,因此完全有可能某处存在明显的错误。

4

1 回答 1

0

问题是使用div(整数除法)而不是div_(HTML 元素)。

类型错误有点奇怪,但源于类型检查器如何尝试推断整个表达式的类型。

class_有类型

class_ :: Text -> Attribute

因此[class_ "list-group"] :: [Attribute]。这很容易。

div有类型

div :: Integral a => a -> a -> a

有一个Integral约束,但更重要的是,输入类型和结果类型必须相同。

在像这样的表达中

div [class_ "list-group"] $ do
  a_ [href_ "#", class_ "menuItem list-group-item rounded-0"] "Item 1"
  a_ [href_ "#", class_ "menuItem list-group-item rounded-0"] "Item 2"

类型检查器得出的结论是[class_ "list-group"],do ...和整个div ... ...表达式具有相同的类型。

我们知道第一种类型,所以我们得出do { a_ ...; a_ ... } :: [Attribute]div [...] $ do ... :: [Attribute]

这个用法div是块中的最后一条语句do,这意味着它的类型也是整个do表达式的类型。

我对下一部分有点模糊,但我认为类型检查器会查看

nav_ :: Term arg result => arg -> result

class Term arg result | result -> arg

和可用的Term实例,并得出结论,因为声明的结果类型是,所以(块)sidebar :: Html ()的第二个参数也必须具有 type ,它是 的别名。nav_doHtml ()HtmlT Identity ()

现在我们有一个冲突:声明的类型签名说第二个参数nav_必须是 a HtmlT Identity (),但推断的类型是[Attribute]

此时类型检查器只是放弃并向用户报告令人困惑的问题。

于 2019-06-04T16:04:16.470 回答