# Html.fragment : List (Html msg) -\> Html msg

**URL:** <https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992>\
**Category:** Request Feedback\
**Created:** [February 23, 2021, 11:35am UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992 "2021-02-23T11:35:50Z")\
**Posts on this page:** 18\
**Page:** 2

<div class="post-metadata">

**Author:** ![Warry](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/warry/32/3998_2.png) [@Warry](https://discourse.elm-lang.org/u/Warry)\
**Post date:** [March 1, 2021, 2:21pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/21 "2021-03-01T14:21:04Z")

</div>

hello !

This topic has been discussed already, I’m still in favour of it, as well as the `Attributes` equivalent (especially for styles):

```
let
    important =
        Html.Attributes.many
            [ Html.Attributes.style "background" "red"
            , Html.Attributes.style "color" "white"
            ]
in
Html.div
    [ important
    ]
    [ Html.text "very important!"
    ]
```

---

<div class="post-metadata">

**Author:** ![Atlewee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/atlewee/32/4603_2.png) [@Atlewee](https://discourse.elm-lang.org/u/Atlewee)\
**Post date:** [March 1, 2021, 3:53pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/22 "2021-03-01T15:53:11Z")

</div>

Would it not make sense in elm to call it Html.batch and Html.Attributes.batch ?

---

<div class="post-metadata">

**Author:** ![Janiczek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/janiczek/32/4516_2.png) [@Janiczek](https://discourse.elm-lang.org/u/Janiczek)\
**Post date:** [March 2, 2021, 3:46pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/23 "2021-03-02T15:46:55Z")

</div>

Yeah I think `fragment` might be too React-specific and not immediately obvious.

- `many` sounds good (understandable) 👍
- `batch` has precedent in Cmd and Sub but I feel like it hints at non-ordered nature of the contents (perhaps I’m just interpolating that from Cmd and Sub) so it’s not my favorite for Html.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 2, 2021, 4:03pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/24 "2021-03-02T16:03:26Z")

</div>

`fromList` would be better

---

<div class="post-metadata">

**Author:** ![Atlewee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/atlewee/32/4603_2.png) [@Atlewee](https://discourse.elm-lang.org/u/Atlewee)\
**Post date:** [March 2, 2021, 4:19pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/25 "2021-03-02T16:19:32Z")

</div>

And maybe Html.concat and Html.Attributes.concat would be Even better 🙂

---

<div class="post-metadata">

**Author:** ![Janiczek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/janiczek/32/4516_2.png) [@Janiczek](https://discourse.elm-lang.org/u/Janiczek)\
**Post date:** [March 8, 2021, 5:42pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/26 "2021-03-08T17:42:14Z")

</div>

@evancz Do you think this would be in principle an OK addition to the virtual-dom / Html / Svg API, or is it not worth it?

---

<div class="post-metadata">

**Author:** ![jfine2358](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfine2358/32/3875_2.png) [@jfine2358](https://discourse.elm-lang.org/u/jfine2358)\
**Post date:** [March 9, 2021, 12:23pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/27 "2021-03-09T12:23:19Z")

</div>

(0) Great question and discussion. I found the examples really helpful.

(1) I think the solution might be to provide in Elm a list literal that produces both of

```elm
["Foo", "Bar", "Save"]

["Foo", "Bar", "Save as new", "Save changes"]

```

(2) This can be done in Python, by using its `*` unpacking operator.

```auto
>>> notSaved = ['Save']
>>> isSaved = ['Save as new', 'Save changes']

>>> ['Foo', 'Bar', *notSaved]
['Foo', 'Bar', 'Save']

>>> ['Foo', 'Bar', *isSaved]
['Foo', 'Bar', 'Save as new', 'Save changes']

```

(3) This change was introduced in Python 3.5 (2013) as a result of the analysis in

> **[PEP 448 -- Additional Unpacking Generalizations](https://www.python.org/dev/peps/pep-0448/)**
>
> The official home of the Python Programming Language

(4) The semantics of `*` avoids needless `div` elements in the Html.

(5) Python also has a `**` unpacking operator for dictionaries.

(6) Does anyone know how to create a bold `*` in markdown?

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [March 9, 2021, 2:03pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/28 "2021-03-09T14:03:30Z")

</div>

> [@jfine2358](#):
>
> (6) Does anyone know how to create a bold `*` in markdown?

Escaping the internal `*` should work: \*\* \* \*\* = **\***

---

<div class="post-metadata">

**Author:** ![jfine2358](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfine2358/32/3875_2.png) [@jfine2358](https://discourse.elm-lang.org/u/jfine2358)\
**Post date:** [March 9, 2021, 2:28pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/29 "2021-03-09T14:28:45Z")

</div>

Thanks. It does work, but you have to look closely. From ‘`\ ***\*** \ ***\*** `’ you get ‘\ ***\*** \ ***\*** ’.

---

<div class="post-metadata">

**Author:** ![jfine2358](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfine2358/32/3875_2.png) [@jfine2358](https://discourse.elm-lang.org/u/jfine2358)\
**Post date:** [March 17, 2021, 11:17am UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/30 "2021-03-17T11:17:34Z")

</div>

(0) Here’s a summary of a useful private conversation with @Janiczek. I’ve made changes to what I said, when I think it’s an improvement.

(1) The starting point was a wish to have something like a list literal, but of variable length. And `Html.fragment` was proposed as a way of achieving this. The two arguments to `div`, `button` and so on are both lists. So any syntactic sugar here might be widely used.

(2) Literals are one way to construct a `List`. They are a convenient shortcut.

```elm
> 1 :: 2 :: 3 :: 4 :: (List.singleton 5)
[1,2,3,4,5] : List number
> [1, 2, 3, 4, 5]
[1,2,3,4,5] : List number

```

(2) By the way, constructing a record requires at least one literal for every record type, and another literal for every modification.

```elm
> type alias Rec = { a : Int , b : String }
> rec = Rec 2 "three"
{ a = 2, b = "three" } : Rec
> rec2 = { rec | a = 4 }
{ a = 4, b = "three" } : { a : Int, b : String }

```

(3) The semantics of Python’s

```python
[a , b, * c, d]

```

when written in Elm is

```elm
[a, b] ++ c ++ [d]

```

or in other words \* c, is equivalent to the admittedly odd

```elm
] ++ c ++ [

```

(4) An alternative approach is

```elm
> c = [3, 4]
[3,4] : List number
> List.concat [[ 1, 2], c, [5] ]
[1,2,3,4,5] : List number

```

(5) Either way, something close to Python’s `*` operator can be achieved in Elm via suitable literals.

(6) @Janiczek notes

> `*` as a language syntax would certainly be more general than `Html.Fragment` . That can be its advantage and disadvantage (probably depending on who you ask).

(7) The Elm compiler does type implication. Also, every element in a list must have the same type. This would allow the compiler to **imply the `*` operator** in most list literals.

(8) For example, if we have the `*` operator then we would have

```elm
> b = [2, 3]
[2,3] : List number
> [1 , *b, 4]
[1,2,3,4] : List number

```

and implying the `*` operator would allow

```elm
> [1 , b, 4]
[1,2,3,4] : List number

```

(9) In this situation a literals such as

```elm
[[], [] ]
[[ 1] ], [[ [ 2] ] ] ]

```

would be ambiguous.

(10) Implying the `*` operator doesn’t need a new `ItemOrList` type, even if the starred identifier comes from outside of a function. I suggest that the compiler adds the stars only when there’s one way to produce type-valid code.

(11) If that is done, then the ambiguous examples in (9) would produce `Type Error`. This is a lack of backwards compatibility. The code could be fixed by adding a type annotation.

(12) To conclude.

1. Something similar to Html.Fragment can already be achieved, via `List` methods. Doing nothing is an option.

2. The `*` operator might be a useful addition to `List` literals.

3. The compiler implying the star is an alternative to adding the `*` operator.

(13) Finally, suppose the compiler implies the `*` operator. Then for example the value of

```elm
[0, 1, 2, aaa, 4]

```

could be any of

```elm
[0, 1, 2, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 7, 8, 9, 4]

```

depending on the value of `aaa` . This language feature might at first confuse beginners. Perhaps, even if it can be implied, we’d benefit from an explicit `*` operator.

---

<div class="post-metadata">

**Author:** ![DullBananas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dullbananas/32/3709_2.png) [@DullBananas](https://discourse.elm-lang.org/u/DullBananas)\
**Post date:** [March 18, 2021, 2:22am UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/31 "2021-03-18T02:22:15Z")

</div>

smh

```elm
fragment : List (Html msg) -> Html msg
fragment =
    Html.span []

```

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [March 18, 2021, 5:32am UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/32 "2021-03-18T05:32:12Z")

</div>

This sometimes works but a lot of the times it doesn’t.

If I have a css rule like ` .stack > * + * { margin-top: 1 rem;}`, your solution will not do the proper thing.

---

<div class="post-metadata">

**Author:** ![evancz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/evancz/32/16_2.png) [@evancz](https://discourse.elm-lang.org/u/evancz)\
**Post date:** [March 18, 2021, 2:51pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/33 "2021-03-18T14:51:51Z")

</div>

I recall looking into `batch` for both Html and Attribute when I was implementing elm/virtual-dom, and I recall a few considerations that led me to not add it at the time:

1. It’s would be quite difficult to implement efficiently. I do not recall the exact specifics, but I think it clashed with certain data structures I was relying on to get the good performance numbers. E.g. how should diffing work when you cannot align nodes one-to-one between frames? Should a fragment be flattened? But wouldn’t that cause catastrophic diffs for all subsequent nodes in an unkeyed setting? Yes! Okay, but then what do data structures look like to protect against that? Very extreme care would need to be taken so that adding such a thing would not push Elm out of the top contenders on perf. (Special care is needed to make sure a JS VM can specialize code, like keeping object shapes perfectly uniform, and I recall thinking that was part of what made this idea difficult.)

2. I did a decent amount of work to make elm/virtual-dom as small as possible while still having great performance, and I suspect that resolving the diffing question above would come at a notable size cost if perf was maintained overall.

3. I had a weird feeling about it. Would it make code more confusing and unpredictable in certain ways? Maybe it is that `func : Html msg -> Html msg` seems to be declaring unambiguously that a single node will be passed in, and with this addition, it’s not saying that anymore. I could not tell if that was bad or neutral. I just had a weird feeling about it.

If you are into this idea, I would recommend working through (1) and (2) to prove that perf is not degraded by such an addition and see what the size change is for Hello World, TodoMVC, etc. If it is degraded, I’d consider that a major mark against the idea. From there, it’s more plausible to have a discussion about (3) whether the “surprise factor” of a `Html msg` actually being 100 nodes during a debug session is an okay price to pay. Seems like a high cost compared to using `++` where the structure of the DOM would be explicit in the code. But like I said, I don’t know really. I just felt weird about it. I personally dropped that line of thought as I came to understand the implementation challenges 😅

Anyway, I hope these recollections are helpful.

---

<div class="post-metadata">

**Author:** ![ymtszw](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/ymtszw/32/2360_2.png) [@ymtszw](https://discourse.elm-lang.org/u/ymtszw)\
**Post date:** [March 18, 2021, 3:11pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/34 "2021-03-18T15:11:23Z")

</div>

Bringing up somewhat related post(my earlier write-up):

> [@On \`none\` patterns](https://discourse.elm-lang.org/t/on-none-patterns/2730):
>
> Currently, passing Http.header "" "something" in a List of headers in elm/http ends up in a runtime exception. I have opened an issue for this. By the way, while I writing up the issue, I pondered this a little more generally. Background Essentially, I wanted to do this: headers = [case fooBar of Foo str -\> Http.header "foo" str Bar -\> Http.header "" "" , ...] I.e. Conditionally add/not add a value within a List. Yes, the runtime ex…

> [@On \`none\` patterns](https://discourse.elm-lang.org/t/on-none-patterns/2730/6):
>
> Very good point, thank you for bring it up! Yes, having batch function might actually be more generally helpful for this. As you pointed out, It IS actually a building block for none function Even without none, it allows us to do the equivalent by batch [] It essentially enables us to flatten Lists!! I found the 3rd point very interesting, related to code modularity. As we are already using Cmd.batch to do things like this: fooCmd : Cmd Msg fooCmd = Cmd.batch [fooDoThis, fooDoThat]…

Thinking out loud about `none` (essentially `batch []`) patterns.

---

<div class="post-metadata">

**Author:** ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)\
**Post date:** [March 18, 2021, 3:20pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/35 "2021-03-18T15:20:46Z")

</div>

I had the same instinct as @Chadtech. React needs the concept of a Fragment for the same reason for a lot of syntax sugar in JavaScript/TypeScript: things are special, so they don’t compose together neatly.

If a JSX Element was just data, then you could compose it together more freely. I find that there is special syntax for a lot of similar things with JavaScript - the ternary conditional operator, conditional chaining syntax, etc. are all just because `null` (and `undefined`) are special things, rather than just another kind of data that composes together like anything else. That’s one of my favorite things about Elm - instead of optional chaining syntax, we have `map` functions which we can use for more than just `Maybe` values, which is a world of difference.

Similar to what @ymtszw mentioned, I find myself building these kinds of patterns often. Some of the patterns I often reach for:

```elm
buttonsView : { isSaved : Bool } -> Html Msg
buttonsView {isSaved} =
  let
    saveButtons : List Html Msg
    saveButtons =
        if isSaved then
            [ buttonView "Save as new" SaveAsNew
            , buttonView "Save changes" SaveChanges
            ]
        else
            [buttonView "Save" Save]
  in
  Html.div []
    (List.concat [
        [ buttonView "Foo" DoFoo
        , buttonView "Bar" DoBar
        ]
        , saveButtons
        ])

```

I also often use `List.filterMap identity` to remove `Nothing` from a list.

```elm
buttonsView : { isSaved : Bool } -> Html Msg
buttonsView {isSaved} =
  Html.div []
    ([ buttonView "Foo" DoFoo |> Just
    , buttonView "Bar" DoBar |> Just
    , buttonView "Save as new" SaveAsNew |> viewIf isSaved
    , buttonView "Save changes" SaveChanges |> viewIf isSaved
    , buttonView "Save" Save |> viewIf (not isSaved)
    ]
    |> List.filterMap identity
    )

viewIf : Bool -> Html msg -> Maybe (Html msg)
viewIf condition html =
    if condition then
        Just html
    else
        Nothing

```

If we did anything to improve the situation, I would say the direction to go would be _less_ special things because that’s what makes Elm lovely to work with. Instead of special things like Fragments, maybe some standard patterns that can be applied generally (not just for views), and perhaps a nice package to encapsulate that pattern in a way the community can build on as a standard convention.

---

<div class="post-metadata">

**Author:** ![Sebastian](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sebastian/32/98_2.png) [@Sebastian](https://discourse.elm-lang.org/u/Sebastian)\
**Post date:** [March 19, 2021, 2:11pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/36 "2021-03-19T14:11:45Z")

</div>

Interesting discussion, initally I’m not keen on the initial fragment concept as I don’t really see the need in Elm. As mentioned in React this is needed because a component cannot return a list.

I usually concatenate list and that works fine.

```auto
let
    buttonWhenSaved = if isSaved then [buttonView ...] else []
    ...
in
div [] (baseButtons ++ buttonWhenSaved ++ buttonsWhenNotSaved)

```

However from this discussion there are two things I would love to see in Elm.

1. NoOp values for Html and Attribute, instead of using `text ""` and `class ""`

2. I think that being able to spread a list inside a list would be a great language feature:

```auto
let
   saveButtons =
     if saved then
        [ buttonView "Save as new" SaveAsNew
        , buttonView "Save changes" SaveChanges
        ]
    else
       [buttonView "Save" Save]
in
div []
  [
     buttonView "Foo" DoFoo
     , ...saveButtons
     , buttonView "Bar" DoBar
  ]

```

---

<div class="post-metadata">

**Author:** ![Janiczek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/janiczek/32/4516_2.png) [@Janiczek](https://discourse.elm-lang.org/u/Janiczek)\
**Post date:** [March 19, 2021, 4:13pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/37 "2021-03-19T16:13:21Z")

</div>

> [@Sebastian](#):
>
> NoOp values for Html and Attribute, instead of using `text ""` and `class ""`

We can pretend…

- [Html.Attributes.Extra.empty](https://package.elm-lang.org/packages/elm-community/html-extra/latest/Html-Attributes-Extra#empty)
- [Html.Extra.nothing](https://package.elm-lang.org/packages/elm-community/html-extra/latest/Html-Extra#nothing)

It’s not 1st-party support and it uses the primitives you mentioned, but at least our code doesn’t need to care about those “implementation details” 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [March 29, 2021, 4:13pm UTC](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992/38 "2021-03-29T16:13:22Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.

[Previous page](https://discourse.elm-lang.org/t/html-fragment-list-html-msg-html-msg/6992.md?page=1)
