I was wondering about the Html type today. Do we have a compelling use case for the
Html a as opposed to
List (Html a)? In which cases do we really care that our argument is a single DOM node?
The reason to ask the question is because if we generally don’t care, the
html library (or a wrapper?) can define its
Html type to always represent a list of DOM nodes. The benefit is that can simplify types, that you don’t have to pick and that you certainly don’t need meaningless wrapper
I’ve done a bit of research. The
http library only has
Html a in argument position on one function, which is
map. Judging from that, such a refactoring seems feasible. At least two other areas remain: low-level details and HTML semantics.
I don’t really expect performance to change that much, because
html is dealing with a lot of lists anyway. However, I don’t know how it’s implemented, so I really can’t judge this.
Regarding HTML semantics, at first I thought
html has to be by itself, but is that really a requirement? For the DOM API it is, so probably it does make sense to have it as a low level type at least.
Browser has the
element function which takes an
Html a so that’s a use case. (what happens if I insert a text node in
So my question is, which APIs or even elements did I miss? Do you want to enforce single DOM nodes in certain cases?
Update: naming idea:
Node for DOM nodes and
Html for multiple
Nodes. Consider it a mass noun.
- it makes the type signatures align with expectations from other APIs (thanks @pdamoc)
Hi @roberth and welcome to the Elm community.
I’m confused a little bit. When you are talking about the
Html a nodes defined in the
Html library, how do you propose to declare the attributes of those nodes in your alternative?
For example, what would
button [ onClick Increment ][ text "+" ] look like in your proposal?
It would look the same. You’d have
text : String -> Html msg
button : List (Attribute msg) -> Html msg -> Html msg
button [ onClick Increment ] (text "+") : Html msg
The button function gets all the information to construct the button, as before.
A big difference why this can be done in Elm
html and not in many other libraries is because
html doesn’t have any setter functions to modify an element. In fact it can not even have setters because you can’t set an attribute on a text node.
html would have
none : Html msg and a
++ operator would be really nice.
I find it very confusing to have the type of an
HTMLElement be the same as the type of its children.
I’m trying to understand what would the benefit of your approach be. I’m also trying to understand what problem are you actually trying to solve here with this redesign.
The real-world problem that this solves is the need for meaningless
div  to turn
List (Html msg) into
Html msg because someone wrote a function that has an
Html msg parameter.
This also means that the community doesn’t have to teach newcomers to always write
List (Html msg) parameters instead of
Html msg. I think Elm does a good job of making it easy to do “The Right Thing”, but this stands out to me.
I agree that the type of
element is a slightly less descriptive with this change, but I don’t think that’s a problem. The difference between “a list of nodes” and “more HTML” seems insignificant to me.
If someone’s function expects a node, give it a node. I think this is perfectly fine to wrap a list with
If you don’t like to have an extra div and would have preferred that that function receives a list, you are free to reimplement it to match your preference.
List of children should look like a
List. It is less surprising to see
List (Html msg) than to discover that an element is actually a list.
It might be so for you but the difference between “a list of nodes” and “a node” is significant. It is easier to model mentally an HTMLElement to one thing than to a list.
If you really want to avoid extraneous divs, feel free to delay the construction of the container. In other words, have your functions return
List (Html msg) and concatenate them like this :
firstPart : Model -> List (Html Msg)
firstPart model =
secondPart : Model -> List (Html Msg)
secondPart model =
someSection : Model -> Html msg
someSection model =
section  ( firstPart model ++ secondPart model )
someSectionAlt : Model -> Html msg
someSectionAlt model =
[ firstPart model
, secondPart model
, lastPart model
|> section 
Indeed I have become more inclined to just use
List (Html msg) in most parameters now and doing so works.
Your example illustrates this approach nicely.
It also has an interesting typo. You wrote
List msg because you were thinking about lists instead of HTML.
Good catch. I have updated the code to the correct form.
What kind of voodoo did I just witness? If this doesn’t make a compelling point, I don’t know what does
This is a great question and discussion so far.
@roberth I think the primary reason
List is used is because Elm functions cannot have a variadiac interface. A parameter can only be bound to a single value, but that value could indeed be a list containing multiple values.
Using your proposed change to the API, how would you represent this Html unordered list?
ul  (li  (text “one”))
Where should we insert
li  (text “two”)?
List a is the way for us to understand that a function accepts a variadic (0 or more) number of
a-typed elements. As much as I love your idea to allow the programmer to forget such complexity, I believe this is a limitation in the language itself - Ie, there’s no way to express a variadiac interface in a language where all functions are curried and lists (or other compound data types) are the only option for specifying a variable number of arguments.
(This is also the reason we sometimes see things like
Html msg type is (conceptually) still appendable and appending still has a neutral element (like
 but named
Html.none). One might even say it’s a Monoid (/me takes cover). So ideally it’s like
ul  (
li  (text one ++ text one) ++
li  (text b)
Is it ok to overload
Instead of overloading
++ we might define
Html as a type alias
type alias Html msg = List (HtmlNode msg).
I think elm-ui resolves this problem by highlighting the semantic differences. Most elements can only have one child and so only take another
Element msg as an argument. Those that have multiple children (and so take
List (Element msg)) do so for a reason made obvious in their name, e.g.
Element.column. Not only does this make it much easier to work out which you need to hand to a given element, but what you have and what the element expects are more often than not already the right thing anyway. If you haven’t looked at it, it’s definitely worth checking out…
@Jess_Bromley, elm-ui seems to provide a really good ‘language’ to describe user interfaces.
This library is a complete alternative to HTML and CSS.
Sadly that’s too big a change for us right now, because it’s very compelling.
HTML semantics seem to embrace its “rose tree” format and always provide some meaning for the juxtaposition of siblings.
elm-ui doesn’t seem to leave that meaning implicit and only defines it for elements that have the explicit purpose of combining elements, such as
row. Interestingly, it does define
Element msg seems to be a bit like
Maybe (Html msg) (where
Html has the usual definition).
I think you make couple of good points that can be formulated in alternative UI library.
Problem is that
Html by it self is not inspectable, so you can’t ask does this div has 4 children? Oh plug one element after second child.
That would maybe get some jQuery smell in elm ,but i don’t know, I may use it couple of times, especially if you realize that you have taken the wrong path in structuring your solution, and deadline is screaming DEPLOYIT!!
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.