I made this module to reduce boilerplate when dealing with enums.
To create an Enum, you first define your custom type:
type Fruit
= Apple
| Banana
| Pineapple
And then you call Enum.create
with a list of your variants, and a toString
function:
enum : Enum Fruit
enum =
Enum.create
[ Apple
, Banana
, Pineapple
]
(\a ->
case a of
Apple ->
"Apple"
Banana ->
"Banana"
Pineapple ->
"Pineapple"
)
This gives you an Enum a
which is a record containing common helper functions, as well as dict and list of the variants, which are useful for things like <select>
elements.
type alias Enum a =
{ toString : a -> String
, fromString : String -> Maybe a
, encode : a -> Value
, decoder : Decoder a
, dict : Dict String a
, list : List ( String, a )
}
So you can then use these like Fruit.enum.decoder
etc.
Curious if you think it’s worth releasing as a package, and what you think of this idea of returning a record of helper functions?
Currently it only supports strings, since that’s how our enums are encoded in JSON. If I were to release it I’d probably extend it to Ints as well.
Here’s the full code of the module, really short actually:
module Enum exposing (Enum, create)
import Dict exposing (Dict)
import Json.Decode as Decode exposing (Decoder, Value)
import Json.Encode as Encode
type alias Enum a =
{ toString : a -> String
, fromString : String -> Maybe a
, encode : a -> Value
, decoder : Decoder a
, dict : Dict String a
, list : List ( String, a )
}
create : List a -> (a -> String) -> Enum a
create list toStr =
let
list2 =
list |> List.map (\a -> ( toStr a, a ))
dict =
Dict.fromList list2
in
{ toString = toStr
, fromString = \string -> Dict.get string dict
, encode = toStr >> Encode.string
, decoder =
Decode.string
|> Decode.andThen
(\string ->
case Dict.get string dict of
Just a ->
Decode.succeed a
Nothing ->
Decode.fail ("Missing enum: " ++ string)
)
, dict = dict
, list = list2
}