# Covering all constructors

**URL:** <https://discourse.elm-lang.org/t/covering-all-constructors/5310>\
**Category:** Learn\
**Created:** [March 12, 2020, 11:23pm UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310 "2020-03-12T23:23:04Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![glasserc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/glasserc/32/2611_2.png) [@glasserc](https://discourse.elm-lang.org/u/glasserc)\
**Post date:** [March 12, 2020, 11:23pm UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310/1 "2020-03-12T23:23:05Z")

</div>

I’m working on making a `Route` type which can be used throughout my project to refer to the possible routes in my frontend and convert them to/from URLs. A common sanity check/test for this kind of thing is to try “round-tripping” routes through the to-URL/from-URL functions to ensure everything is covered and consistent. So I wrote a fuzzer for my `Route` type, which was straightforward.

I expect this type will change as I add pages to my project. When this happens, I will have to remember to update the fuzzer. If I don’t, my test will become invalid because the new cases I added will not be tested in the round trip.

Has anyone come up with a clever way to ensure that the fuzzer stays in sync with the underlying type? One idea I had was to add a dummy `reminder` function just under the fuzzer which does an exhaustive pattern match on the `Route` type. Then, if a constructor is added, at least the `reminder` function will break, and hopefully that will serve as a reminder to update the fuzzer. But maybe there’s another way?

Is this a non-issue for other people, perhaps because you keep your fuzzers closer to the underlying type (as hinted at in e.g. [Where to put encoders, decoders and generators?](https://discourse.elm-lang.org/t/where-to-put-encoders-decoders-and-generators/711/12))?

---

<div class="post-metadata">

**Author:** ![jfmengels](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jfmengels/32/3124_2.png) [@jfmengels](https://discourse.elm-lang.org/u/jfmengels)\
**Post date:** [March 13, 2020, 8:03am UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310/2 "2020-03-13T08:03:18Z")

</div>

I think the established pattern at this point is using a `reminder`, just like you said.

That is also what we used to do at my workplace. Now, we use a custom [`elm-review`](https://package.elm-lang.org/packages/jfmengels/elm-review/1.0.0/) rule instead. By convention, we consider all values that look like `allXyz : List Xyz` to need to have all the constructors of the type Xyz, which gives us the following error message

```auto
-- ELM-REVIEW ERROR ------------------------------------------ src/Route.elm

NoMissingTypeConstructor: `allRoutes` does not contain all the type constructors for `Route`

11| allRoutes : List Route
12| allRoutes =
    ^^^^^^^^^
13| [ HomePage

We expect `allRoutes` to contain all the type constructors for `Route`.

In this case, you are missing the following constructors:
  - SomePage

```

The code for it is in [this gist](https://gist.github.com/jfmengels/92614e7ff4cf91a9c573c90f0d95a4fb). I will probably make a package for it at some point. The limitation is that you can only do this for types that are defined in the same file as the `allXyz` constant, but that limitating will change soon with an upcoming release of `elm-review`.

What I regret about this pattern, is that you lose this safety net as soon as someone renames the `allXyz` constant. But the `reminder` is brittle in a similar way, so 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![ni-ko-o-kin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/ni-ko-o-kin/32/2693_2.png) [@ni-ko-o-kin](https://discourse.elm-lang.org/u/ni-ko-o-kin)\
**Post date:** [March 13, 2020, 8:03am UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310/3 "2020-03-13T08:03:33Z")

</div>

The reminder-function is the only thing that works AFAIK.

There was a proposal:

> [@\`enumerate\` function for non-infinite custom types - proposal](https://discourse.elm-lang.org/t/enumerate-function-for-non-infinite-custom-types-proposal/2636):
>
> tl;dr I propose the compiler would expose a “magical” function enumerate : Type a -\> List a (for lack of better syntax) that would enumerate non-infinite types into a list: type MyType = Foo | Bar Baz type Baz = A | B | C enumerate Baz --\> [A, B, C] enumerate MyType --\> [Foo, Bar A, Bar B, Bar C] Motivation I’m regularly encountering situations where I have a custom type for which I need all its values to be processed (shown, aggregated, …). For example [this thread](https://discourse.elm-lang.org/t/typesafe-url-parser-oneof-usage/1964). Cu…

---

<div class="post-metadata">

**Author:** ![glasserc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/glasserc/32/2611_2.png) [@glasserc](https://discourse.elm-lang.org/u/glasserc)\
**Post date:** [March 14, 2020, 9:18pm UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310/4 "2020-03-14T21:18:49Z")

</div>

Thanks, this seems like a great use of `elm-review`.

---

<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 24, 2020, 9:18pm UTC](https://discourse.elm-lang.org/t/covering-all-constructors/5310/5 "2020-03-24T21:18:53Z")

</div>

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