---
title: Understanding Elm's Type Mismatch Error
teaser: Breaking down Elm's Type Mismatch error in basic and complex cases.
tags: elm,functional programming,debugging
author: Hawley Brett
published_on: 2020-07-20
---

A big reason people love Elm is the compiler’s helpful error messages. The
compiler not only points out what’s wrong, but also includes hints for how to
fix it.

One of the first error messages you’ll run into is the “Type Mismatch” error.
This error is fundamental to Elm’s enforcement of its strict type system and
tells you when a function is expecting a different type of argument than the one
it has been passed.

In a basic case, this error is straightforward, so first we’ll wrap our heads
around what this error is fundamentally about. But in more complex cases, like
when you’re passing functions as arguments to other functions, this error can be
confusing if you don’t know what to look for.

## Type Mismatch Basics

You’ll see the “Type Mismatch” error when, for example, you pass a `String`
instead of an `Int` to a function expecting an `Int`.

Given this function:

```Elm
showAge : Int -> String
showAge age =
    String.fromInt age
```

If you called `showAge` with a string, like so:

```Elm
showAge “invalid argument”
```

You’d get the Type Mismatch error:

```Elm
TYPE MISMATCH - The 1st argument to `showAge` is not what I expect:

Html.text (showAge "invalid argument")

                  #^^^^^^^^^^^^^^^^^^#
This argument is a string of type:

   #String#

But `showAge` needs the 1st argument to be:

   #Int#
```

This makes sense -- an `Int` is not a `String`, so the compiler is saying the
wrong type is being passed to the function `showAge`. The compiler will not
allow you to pass the wrong types of arguments to a function. We can’t use a
`String` in place of an `Int`, and so the compiler lets us know that we’re using
the wrong type. This error is fundamental to enforcing that arguments passed to
a function are of the correct type.

## Complex Type Mismatch Cases

While this error is usually clear, you might run into circumstances where it’s
more confusing. This often happens when you are passing functions to other
functions. In most Elm code and functional code more broadly, you’ll see
functions being passed to other functions quite commonly. This results in a
chain of functions that each expect certain types of arguments, and if one
argument in the chain is wrong, you’ll get the Type Mismatch error. But it might
be hard to see where things are going awry.

Consider this code, where we want to pass a `name` and an `age` to the
`profileDetails` function, and then we’ll pass the `profileDetails` function to
the `div` function.

If we pass only the first argument, `name`, to `profileDetails`, leaving out
`age`, like so:

```Elm
userProfile : User -> Html msg
userProfile user =
    div [] [ profileDetails user.name ]
 
profileDetails : String -> Int -> Html msg
profileDetails name age =
    div [] [ text name, text <| String.fromInt age ]
```

We get the Type Mismatch Error:

```Elm
TYPE MISMATCH - The 2nd argument to `div` is not what I expect:

2|     div [] [ profileDetails user.name ]
               #^^^^^^^^^^^^^^^^^^^^^^^^^^^^#
This argument is a list of type:

   List #(Int -> Html msg)#

But `div` needs the 2nd argument to be:

   List #(Html msg)#

#Hint#: I always figure out the argument types from left to right. If an
argument is acceptable, I assume it is “correct” and move on. So the problem may
actually be in one of the previous arguments!
```

*Why do we get this error?*

The first thing we'd probably look at, given the text of the error message, is
the type annotation of `profileDetails`. If `div` expects a `List (Html msg)`,
we'd double check what `profileDetails` is doing. So we look at its type
annonation, and we see -- well, `profileDetails` results in an `Html msg`, and
it’s already in a `List` when it’s passed to the `div` function. Isn’t that
exactly what `div` expects?

We'd then look at the hint, which reminds us that the compiler looks at the
arguments left to right, so the first argument to `div` here, an empty list,
could also be wrong. But we're confident that this empty list is an acceptable
first argument here.

The real problem is that `profileDetails` is simply missing the second argument
that it expects! `profileDetails` expects the user’s name, a `String`, and their
age, an `Int`. So far we've only passed `profileDetails` the `name`. All we need
to do is pass the `age` to `profileDetails` as well.

This now compiles:

```Elm
userProfile : User -> Html msg
userProfile user =
   div [] [ profileDetails user.name user.age ]

profileDetails : String -> Int -> Html msg
profileDetails name age =
   div [] [ text name, text <| String.fromInt age ]
```

Why then did the compiler not say, “The arguments to `profileDetails` are not
what I expect : `profileDetails` expects a `String` and an `Int` but was only
given a `String`”? It might seem like the real problem was in the arguments
passed to `profileDetails`, not the ones passed to `div`. But the compiler
accepts `(profileDetails name)` as valid in itself, just not as the second
argument to `div` when in a List. And if the compiler complains about passing
too many arguments to a function, why does it not complain about too few?

The answer has to do with how Elm works, and a concept called “Partial
Application”. When the `name` is passed to `profileDetails` but not the `age`,
we’d say that `profileDetails` has been “partially applied”. In Elm, even though
we’d generally say that `profileDetails` is a function, implying that it is a
single function, it is in fact a set of functions. The first function takes the
`name` and returns a function that takes the `age`, and that function finally
returns an `Html msg`. So really it’s two functions. If `profileDetails` also
took a "Bio", then it would be three functions under the hood, each one passing
its resulting function to the next, until it produces the final data structure
as represented in the annotation. This process is called “currying”, and it’s
fundamental to how Elm works.

## Rule of Thumb

If you see a function in a Type Mismatch error, you’ll want to check that the
function has been passed all its arguments (or the number you're expecting to
pass it at that point, since you can use partial application deliberately too).
In the above error, where it says the type is: `List #(Int -> Html msg)#`, we
can tell that `(Int -> Html msg)` represents a function because of how it's
annotated with the arrow, just like we annotate functions normally. You can
think of it like the function is waiting for an argument, in this case the
`age`, an `Int`. Here the function is also in a `List` because we've put it in
the second list to passed `div`, `div [] [ profileDetails user.name ]`. When you
see a function in the error message, you can likely skip the other debugging
steps and go straight to checking if the function has been partially applied
when you didn't mean it to be.

While a full examination of
[currying](https://medium.com/@alexander.s.boring/currying-with-style-in-elm-65820f9d02d6)
and [partial
application](https://elmprogramming.com/function.html#partial-function-application)
is outside the scope of this post, what’s valuable to remember is that each
argument to a function in truth represents a distinct function with that
argument applied. It therefore *must* be legal for a function to accept fewer
arguments than its total, because that’s what’s already happening each time you
pass an argument to a function in Elm. If you come to expect that a function may
be passed fewer arguments than its total, when you see a function annotation in
the Type Mismatch error you’ll know that this is something to look out for. You
might even find yourself using partially applied functions on purpose!
