Is it possible to iterate over union type in Elm?

The problem with declaring a function like:

type Foo 
  = Bar 
  | Baz

enumFoo = 
  [ Bar 
  , Baz ]

is that you will probably forget to add new enums to it. To solve this, I've been playing with this (hacky, but less hacky than the idea above) idea:

enumFoo : List Foo
enumFoo =
  let
    ignored thing =
      case thing of
          Bar ->  ()
          Baz -> ()
          -- add new instances to the list below!
  in [ Bar, Baz ]

This way you at least get an error for the function and hopefully don't forget to add it to the list.


Unfortunately, no. It is not possible.

For a simple type with a finite number of values like your Color type it might seem like the compiler should be able to generate such a list. As far as the complier is concerned though, there is no difference between your type and a type like

type Thing = Thing String

To iterate over all the values of type Thing would then require iterating over all the values of type String.


This does not exactly answer your question, but since Elm is so similar to Haskell, I am probably not the only one wondering what the Haskell side of the story is.

So in Haskell (showing ghci) you can do:

Prelude> data Color = Red | Blue | Green | Black deriving (Show, Bounded, Enum)
Prelude> [minBound..maxBound]::[Color]
[Red,Blue,Green,Black]

Maybe a future version of elm will borrow from that.

Edit: I found Getting a list of all possible data type values in Haskell which also answers this.


Oh course you can do it. Just not automatically via the compiler.

type Foo 
   = Bar 
   | Baz
   | Wiz

-- just write this for types 
-- you wish to use as enumerations 
enumFoo = 
   [ Bar 
   , Baz
   , Wiz ]

This works just fine, but obviously would be nicer and exhaustivity checked, if enumeration is ever supported by the compiler.

colorList = 
ul
    []
    List.map colorListItem enumFoo

Tags:

Iteration

Elm