# What's Weird with Maybe List

When modeling data in a typed language like Elm or Haskell, some combinations of types are a bit strange. Take `Maybe (List a)`. It has two empty states: `Nothing` and `Just []`. Does your code distinguish between these two? Or do they mean the same thing?

## Same thing

Lists already have an empty state: `[]`. If you only need to model “list of values” and “no values” then you can rely on `List` alone.

In the following code, we see that `Nothing` and `Just []` are semantically the same: they represent the absence of results.

``````view : Maybe (List Int) -> Html a
view calculation =
case calculation of
Just numbers -> viewResults numbers
``````

Wrapping in `Maybe` doesn’t add any extra information so we can simplify our case statement by dropping the `Maybe` entirely.

``````view : List Int -> Html a
view calculation =
case calculation of
_ -> viewResults calculation
``````

## Different things

Sometimes, `Nothing` and `Just []` are being used to represent different states.

``````view : Maybe (List Int) -> Html a
view calculation =
case calculation of
Nothing -> text "In Progress"
Just numbers -> viewResults numbers
``````

A custom union type will do a better job at communicating the semantic differences. Now you can see at a glance what possible states a calculation can have.

``````type Calculation
= InProgress
| NoResults
| Results (List Int)
``````

## Getting fancy

Observant readers might have noticed that it’s still possible to end up with the weird state `Results []` using the union type defined above. Since we’ve separated out the empty state from the list, we might want to get fancy and guarantee a non-empty list for `Results`.

``````type Calculation
= InProgress
| NoResults
| Results (List.NonEmpty Int)
``````

## Legitimate uses of `Maybe (List a)`

Does this mean that we should avoid `Maybe (List a)` at all cost? No. Consider getting the head of a doubly-nested list:

``````[[1,2], [3,4]]
|> List.head -- returns Just [1,2]
``````

`Maybe (List a)` is a perfectly valid return type here. It represents a list that may or may not be present. It does not carry any extra implicit semantic meaning.

Returning an optional list often makes sense when querying another data structure. Not only does it correctly model the uncertainty in the querying, it also allows functions to be chained nicely with other `Maybe` helpers.

``````firstChild : Int -> MyTree a -> Maybe (MyTree a)
firstChild id myTree =
myTree
|> MyTree.childrenOfNode 10
The `Maybe (List a)` is a type that introduces ambiguity when data modeling. Depending on what you’re trying to represent, a simple `List a` or a custom union type may better model your system. Don’t discount it entirely though. It can often make sense as the return type of a query function.