10

Consider this snippet:

type alias Model =
    { x : Int }


testFunc : Model -> Html String
testFunc model =
    div [] []

I am very confused here. div is a function that returns a Html msg. But testFunc returns Html String.

How does this compile? Am i missing out on some very basic understanding here?

user3282666
  • 640
  • 1
  • 7
  • 21
  • Related: https://stackoverflow.com/questions/37363294/what-does-a-function-with-2-values-on-the-right-side-mean-model-html-msg – Rotareti Oct 29 '17 at 03:26

2 Answers2

10

You can kind of treat msg like Generics in Object Oriented programming. This is not technically correct, though the concepts are similar. Just keep in mind that generic is not the correct terminology strictly speaking.

With that said, div is a function that returns a value of Html with a 'generic' type of msg (where msg could be any type). This would be written as Html<A> in Java or C#, where is A is a placeholder for any type.

Elm has type inference, so when the return type of testFunc is Html String Elm infers that msg must therefore be a String type.

Also note Elm requires the generic type be lower case (e.g msg). It's often confusing in Elm code as people will often define a real type of Msg and also name the generic placeholder type msg.

Community
  • 1
  • 1
Pete
  • 2,196
  • 1
  • 17
  • 25
  • Would you mind expanding on the technical difference between the generic types in elm and in OO programming? Is there a practical difference between *substituting* (OOP) and *infering* (Elm) the type? It's mentionned in the elm guide as a *type variable*, but at least from there, I could not see any difference. Thanks in advance! – Benjamin Audren Jan 13 '17 at 13:51
  • 1
    Someone else would probably do better than me in explaining the technical differences :) Conceptually though, I find they are very similar. Re type substituting vs type infering: OOP Substitution is concerned with sub types and class hierarchy. E.g if a method takes an `Animal` object as an argument, you can also use a `Dog` object (assuming the `Dog` class inherits from `Animal`). Whereas type infering is more about the compiler working out a type without the code explicitly setting it. E.g with `let a = "some text"`, Elm can deduce from the code that `a` must be of type `String` – Pete Jan 13 '17 at 14:32
  • Ok, makes sense. In practice I see so little difference that the two things merged in my mind. Thanks for the comment – Benjamin Audren Jan 13 '17 at 16:41
4

Bear in mind the difference between lower-case and upper-case type definitions. Lower-case msg in the signature of div is a generic type. It could have been named a, or anything else that starts with a lower-case.

In your definition of testFunc, you are simply using the div with a return type of String, which is not an issue for the elm compiler: this could very well be your Msg type.

In other words, the return type of div is not Html Msg, but is instead Html msg. This allows you to use it with whatever messages your component define, and makes it truly generic.

Benjamin Audren
  • 374
  • 2
  • 16
  • How can a `Html String` which is a concrete type accept `Html msg` which is a generic type? – user3282666 Jan 13 '17 at 08:44
  • 2
    That's the other way around. The generic type `Html msg` accept being returned as a `Html String`, because `msg` could really be anything. For the list functions, for instance, they are usually defined as accepting `List a`, and not specifically `List String`. This way you can use them with `List Int`, etc... without having to redefine a new function. Checkout [this reddit discussion](https://www.reddit.com/r/elm/comments/4jgv6x/beginner_question_on_the_elm_type_system_in_the/) on the topic, it might help you. – Benjamin Audren Jan 13 '17 at 09:29