It looks like a lot of beginners (including myself) get confused with Html msg and Html Msg . Searching for explanations brings a lot of helpful discussions and explanations [1], [2], [3], [4]. And at the end of that reading I thought I did understand the difference, but that feeling vanished when I started going through the source of elm-spa-example code base. Here are some snippets:

type Article a = Article Internals a

mapAuthor : (Author -> Author) -> Article a -> Article a mapAuthor transform (Article info extras) = Article { info | author = transform info.author } extras

fromPreview : Body -> Article Preview -> Article Full fromPreview newBody (Article info Preview) = Article info (Full newBody)

Type constructors

As I was going through the source code of different projects I got confused with many things, one of which was type constructors. If you look at one of the snippets above it has Article on both left and right side of the equation. How does it work?

In Elm it is common to see this pattern [5] [6] [7]. The Article on the left side is a type definition. We are telling Elm that we want a new type called Article . The right side creates a function called Article which essentially acts as constructor function that accepts two arguments and returns an instance of Article . I am not a Java developer but I liked an example from Mike Knepper to illustrate this in another language:

public class Article { public Article(Internals i, Object a) { // ... } }

We can create a simplified code to illustrate this pattern:

> type User = User String > User <function> : String -> User > myUser = User "Batman" User "Batman" : User

Here we have a type User and a type constructor also called User that accepts a String and returns type User .

Phantom types

Now that I could understand type annotations for different functions, it was time to get back to Html msg and similar constructs. And this is where phantom types come into play.

Phantom types are usually referred to advanced Elm usage, however these are instrumental to understanding what does List a , Article a , or Html msg (which can be written as Html a too) mean and what that a is.

Elm Guide has a nice explanation of type variables. During the definition we don't care what the type of that variable is, it can be an Int , a Float , or something else. The result of the function doesn't depend on the type of variable. A List.length definition doesn't need to know if you're passing a list of characters or tuples, the result will always be an integer, i.e. length of the list. But List.reverse not only takes a generic type but also returns that:

> List.reverse <function> : List a -> List a

The reverse can receive any type and Elm guarantees you that you will receive the exact same type back. So if we were to give it a list of strings, we will get a list of strings back too. Let's try that concept with our own custom type.

In US people measure temperature in Fahrenheit, in Europe in Celsius, and scientists use Kelvins to measure colour temperature of stars.

type Temperature = Temperature Int

We can now have define our temperature in the app:

> temperature = Temperature 10000 Temperature 10000 : Temperature

No matter the scale, it is still pretty high temperature. But what exactly are we dealing with? Are we looking at Earth values? Is it Europe? Or US? Or maybe our Sun? We need to define the scale:

type Fahrenheit = Fahrenheit Temperature type Celsius = Celsius Temperature type Kelvin = Kelvin Temperature

And can now work with different temperatures:

newYorkTemperature = Temperature 40 newYorkTemperatureInFahrenheit = Fahrenheit newYorkTemperature -- Or we can make it all in one line temperatureInNewYork = Fahrenheit (Temperature 40)

Now that we have different scales we can create functions to add, subtract, and convert between each:

diff : Fahrenheit -> Fahrenheit -> Fahrenheit diff (Fahrenheit (Temperature a)) (Fahrenheit (Temperature b)) = Fahrenheit (Temperature (a - b)) f1 = Fahrenheit (Temperature 40) f2 = Fahrenheit (Temperature 30) diff f1 f2 -- Fahrenheit (Temperature 10) : Fahrenheit

For each scale we would need to create an almost exact same function. The only thing that would change is the scale type. This can be simplified using phantom types. First we need to re-define our types to use type variable:

type Temperature a = Temperature Int type Fahrenheit = Fahrenheit type Celsius = Celsius type Kelvin = Kelvin

With these types it is now possible to specify temperature in major cities and even outside the Earth:

newYorkTemperature : Temperature Fahrenheit newYorkTemperature = Temperature 31 -- Temperature 31 : Temperature Fahrenheit parisTemperature : Temperature Celsius parisTemperature = Temperature 8 -- Temperature 8 : Temperature Celsius tempOfTheSum : Temperature Kelvin tempOfTheSum = Temperature 5778 -- Temperature 5778 : Temperature Kelvin

Finally, we need to create just a single diff function that could work with Fahrenheit, Celsius, and Kelvin scales:

diff : Temperature a -> Temperature a -> Temperature a diff (Temperature a) (Temperature b) = Temperature (a - b) -- We're passing two temperatures in Fahrenheit diff chicagoTemperature newYorkTemperature -- Now we're passing two temperatures in Celsius to the same function diff londonTemperature parisTemperature -- Finally we can compare temperature on the Sun and Proxima Centauri diff theSun proximaCentauri

Difference between msg and Msg

Now that it is hopefully clear what Html a is (which is the same as Html msg ), the difference between Html Msg and Html msg will be easy to explain.

Our Elm program produces HTML which gets rendered on the screen, and then the computer sends back messages like "button clicked" or "form submitted". Since it is a convention to call the type of message simply Msg (and not Message or Event ), beginner developers get confused. This is especially true with simple render functions that do not produce any messages:

renderUser : User -> Html Msg renderUser user = text user.fullName -- since the above function doesn't produce any messages of type `Msg` -- we can swap Msg with msg renderUser : User -> Html msg renderUser user = text user.fullName