I am currently in the process of rewriting an HTML file in Lucid for use with a Spock web server. However, for some reason this particular snippet gives me an error:
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"
Namely, the error is:
Couldn't match type `[Attribute]'
with `HtmlT Data.Functor.Identity.Identity ()'
arising from a use of `nav_'
I noticed that removing the div and just having the h3
fixes the problem, but that is not what I want. I did some googling to try to find the issue, but from what I could see the library does not have that many examples online that I could try to look at. Stackoverflow and Reddit searches did not reveal anything either.
This is my first actual project where I have used Lucid, so it is entirely possible that there is an obvious blunder somewhere.
The problem is the use of
div
(integer division) instead ofdiv_
(HTML element).The type error is slightly bizarre, but arises from how the type checker tries to infer a type for the whole expression.
class_
has typeThus
[class_ "list-group"] :: [Attribute]
. That's easy.div
has typeThere is an
Integral
constraint, but more importantly, both input types and the result type must be the same.In an expression like
the type checker concludes that
[class_ "list-group"]
,do ...
, and the wholediv ... ...
expression have the same type.We know the first type, so we conclude
do { a_ ...; a_ ... } :: [Attribute]
anddiv [...] $ do ... :: [Attribute]
.This use of
div
is the last statement in ado
block, which means its type is also the type of the wholedo
expression.I'm a bit fuzzy on the next part, but I think the type checker looks at
and
and the available
Term
instances, and concludes that because the declared result type issidebar :: Html ()
, the second argument tonav_
(thedo
block) must also have typeHtml ()
, which is an alias forHtmlT Identity ()
.Now we have a conflict: The declared type signature says the second argument of
nav_
must be aHtmlT Identity ()
, but the inferred type is[Attribute]
.At this point the type checker just gives up and reports the confusing problem to the user.