paint-brush
On iterating and decoding sum types in Elmby@kaisersly
270 reads

On iterating and decoding sum types in Elm

by Sylvain KiefferMay 3rd, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

<em>EXPERIMENTAL</em>

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - On iterating and decoding sum types in Elm
Sylvain Kieffer HackerNoon profile picture

EXPERIMENTAL

Thanks to imright_anduknowit and Enumerable_any on Reddit for their suggestions.

In Elm you don’t have a native way to list all tags in a sum type.

Let’s say we have a Fruit type defined as :




type Fruit= Orange| Lemon| Apple

How can you create a list of all fruits ([Orange, Lemon, Fruit]) without missing one ?

First, let’s create a function nextFruit which given a Fruit will return a Maybe Fruit which represent the next fruit in the sum :

nextFruit : Maybe Fruit -> Maybe FruitnextFruit maybeCurrentFruit =    case maybeCurrentFruit of        Nothing ->            Just Orange        Just currentFruit ->            case currentFruit of                Orange ->                  Just Lemon                Lemon ->                  Just Apple                Apple ->                  Nothing

Next, let’s create our Fruit list :












fruitList : List FruitfruitList =letbuildFruitList : Maybe Fruit -> List Fruit -> List FruitbuildFruitList maybeCurrentFruit allFruits =case maybeCurrentFruit ofNothing ->allFruitsJust currentFruit ->buildFruitList (nextFruit maybeCurrentFruit) (currentFruit :: allFruits)inbuildFruitList (nextFruit Nothing) []

If you run fruitList you will get [Apple, Lemon, Orange].

Now, if you add Banana in Fruit, you will get a compiler error saying that the case in nextFruit doesn’t handle the Banana possibility. You’ll have to rewrite it :

nextFruit : Maybe Fruit -> Maybe FruitnextFruit maybeCurrentFruit =    case maybeCurrentFruit of        Nothing ->            Just Orange        Just currentFruit ->            case currentFruit of                Orange ->                  Just Lemon                Lemon ->                  Just Apple                Apple ->                  Just Banana                Banana ->                  Nothing

Ok, let’s be honest : you can make errors while writing the nextFruit function but 1/, you will be warned that a new tag has been added to the type and 2/, you can generate this code from the type declaration.

The final touch will be writing a function that given a String will return a Maybe Fruit :





fruitFromString : String -> Maybe FruitfruitFromString fruitString =fruitList|> List.filter (\x -> toString x == fruitString)|> List.head

fruitFromString “Apple” will return Just Apple, fruitFromString “Pineapple” will return Nothing.

You can generalize fruitList :












enumList : (Maybe a -> Maybe a) -> List aenumList nextEnumFn =letbuildEnumList : Maybe a -> List a -> List abuildEnumList maybeCurrentEnum allEnums =case maybeCurrentEnum ofNothing ->allEnumsJust currentEnum ->buildEnumList (nextEnumFn maybeCurrentEnum) (currentEnum :: allEnums)inbuildEnumList (nextEnumFn Nothing) []

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.

To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!