# Enumerating Union Types in Elm

## Problem statement

There are times when you want to enumerate a union type. A common example is to render the \<option> elements within a \<select>. In general each disjoint component of the union may have varying data associated with it.

{% hint style="info" %}
*Custom Types is the official Elm naming and is commonly/formerly known as a (disjoint) Union or Sum types. I'll keep using the Union types naming as it makes sense to me.*
{% endhint %}

Let's start with a simple Union type used effectively like an enum of other languages:

```
type CarMake = AlfaRomeo | BMW | Ferarri | Ford | Honda | McLaren | Mercedes | Renault
```

Commonly a solution to having this accessible for enumeration is to manually define a List:

```
carMakes = [ AlfaRomeo, BMW, Ferarri, Ford, Honda, McLaren, Mercedes, Renault ]
```

The problem of course with this is that we have two parallel definitions that must be manually kept in sync which is exactly the sort of thing computers, compilers and type systems specifically should solve.

Note that we did add some information rather than merely performing double entry. The `carMakes` list defines an ordering whereas the `CarMake` type does not. The Elm language and compiler could infer this from the type definition and provide an enumeration mechanism but that's not part of the language.

So let's get on with it and see what's possible. Elm does ensure exhaustive case matching of Union types.

```
noop : CarMake -> CarMake
noop x =
    case x of
        AlfaRomeo -> x        
        BMW -> x
        ...
        Renault -> x
```

Now if in the above code one of the component types was missed, the compiler would issue an error. This by itself doesn't solve our need. The main problem is that each case is processed independently and we don't have a way of processing every path to produce the full set of values. Even if we fed it our manual list of `carMakes` it would only be able to produce the same set we put in replicating any accidental omission.

What we can do is what an accountant would do in such a situation, double-entry and cross check. We can create a `successor` definition:

```
successor : Maybe CarMake -> Maybe CarMake
successor m =
    case m of
        Nothing -> AlfaRomeo
        Some c ->
            case c of
                AlfaRomeo -> BMW
                BMW -> Ferarri
                ...
                Mercedes -> Renault
                Renault -> Nothing
```

To produce a list from the `successor` definition we can start with `Nothing` and produce each `CarMake` until we end with `Nothing`.

```
carMakes2 = ... [Work in progress]
```

All that's left now is to assert `carMakes` is the same as `carMakes2` .

We can do one better by writing this check once rather than for each Union type.

```
checkUnionSuccessor : List X -> Maybe X -> Maybe X -> Bool
checkUnionSuccessor xs successor =
    ... [Work in progress]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.keithkim.org/code-patterns/enumerating-union-types-in-elm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
