Reputation: 23
I'm learing Elm and trying to understand how type annotations for generic functions are written. (Not sure "generic function" this is the right term for this in Elm, please advise.)
Given the following code:
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
type Msg = EmailChanged String | PasswordChanged String
formView label msg = div [] [text (label ++ ": "), input [onInput msg] []]
main = div [] [formView "Email" EmailChanged, formView "Password" PasswordChanged]
What is the reasoning behind the formView
function being annotated like this
formView : String -> (String -> msg) -> Html msg
and what is the reasoning behind this annotation for the function not being right?
formView : String -> msg -> Html Msg
Upvotes: 0
Views: 58
Reputation: 21005
The types are 'inferred' recursively. You wrote
formView label msg = div [] [text (label ++ ": "), input [onInput msg] []]
Note how the msg
that you pass in is used by onInput
. onInput is defined in the standard library as
onInput : (String -> msg) -> Attribute msg
So the parameter you called msg
needs to have the type String -> msg
. If nothing else in your code contradicts that then your code will compile. If some other use of msg contradicts with that inference, then the compiler will force you to reconcile the difference.
In your case, you passed to formView EmailChanged
. You declared this as a custom type that is completed with a String. Behind the scenes, elm created a function that takes a String and returns Msg
and called it EmailChanged
and it was this latter function that you passed in and that met with the expected type. This last little bit of magic takes a bit of getting used to, but it ubiquitous in Elm so you will quickly become familiar.
Upvotes: 4