typeselmelm-architecture

What is `init : () -> (Model, Cmd Msg)` annotation?


In official Elm website there is a init function definition I don't understand:

init : () -> (Model, Cmd Msg)
init _ =
  ( Loading
  , Http.get
      { url = "https://elm-lang.org/assets/public-opinion.txt"
      , expect = Http.expectString GotText
      }
  )

So init function returns a tuple, then why not define its notation as:

init: (Model, Cmd Msg)

But in their sample init returns a function that returns a tuple. Is this true?

And how to read () in init : () -> (Model, Cmd Msg)? For example can I say from anything return a tuple?


Solution

  • Yes, init is a function. () is called the "unit" type. It's a type that has only one value, (), which is also called "unit".

    Now I'm sure you're asking "Well that seems pretty useless. What's the point of having a function argument that can ever only be one thing?". The answer is that it's very useful if you write something generic that might take something, but don't always have to.

    In this case, Browser.element specifies that init should have the type flags -> ( model, Cmd msg ), where flags is a type variable that can be anything. Since Browser.element does not constrain flags in any other way, you can replace it with whatever you want, and it should still compile.

    Note however that Browser.element is a bit magic. At runtime, Elm will look at the type you've assigned to flags and expect you to pass it a value of that type from JavaScript. If you don't, this is one of very few instances where Elm will fail at runtime (although, technically, it will fail before any of your Elm code runs because you've made a mistake on the JavaScript-side). Specifying () here means you're not expecting any flags.

    How flags work are explained in more detail in the guide