Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elm "type" syntax - where is value coming from?

Tags:

syntax

elm

I am very new and currently trying to learn Elm. I am coming from JS/React and haven't had any previous RFP experience.

I am in the Guide right here: http://guide.elm-lang.org/architecture/user_input/text_fields.html

The part I have problems with is update and view:

-- UPDATE

type Msg
  = Change String

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }


-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ input [ placeholder "Text to reverse", onInput Change ] []
    , div [] [ text (String.reverse model.content) ]
    ]

Let's start with the Msg declaration. The Guide says:

It takes one argument, in this case the Change function which was created when we declared the Msg type:

Change : String -> Msg

I don't see how this happened here:

type Msg
  = Change String

How did we defined a Change function here? How did we define how that function works? To me it looks like we just declared the type of Msg, which somehow contains whatever Change is and the type String.

My second question is about the update:

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }

To me this looks like update is a higher order function, which takes a Msg and returns a function Model -> Model. But then we define a function with two parameters. Does Msg -> Model -> Model just means all but the last part are parameters?

Then we call the Change function:

Change newContent ->
          { model | content = newContent }

What I don't get there is the arrow. Usually the arrow comes after a param definition. But here we have the result of a function before the ->.

I hope my questions make sense, I am just very confused with this (presumably awesome) language.

like image 298
MoeSattler Avatar asked May 20 '16 18:05

MoeSattler


2 Answers

When you declare type Msg = Change String you're declaring a single type (Msg) with one Constructor that accepts a String.

See the Elm guide section on Union Types (AKA Algebraic Data Types, ADTs).

Here's a sample:

type User = Anonymous | Named String

So creating the type User also created constructors named Anonymous and Named. If you want to create a User you must use one of these two constructors

Constructors are functions, so you call them like Change "a string" (returns type Msg)

Constructors also provide the ability to use pattern matching to extract the inner value in a union type. This is the use of -> that you weren't familiar with.

case msg of
  Change theString -> ... use theString ...

Your second question;

To me this looks like update is a higher order function, which takes a Msg and returns a function Model -> Model

Yes, that's more or less what's happening. The precedence rules for function application mean that you can call them without parenthesis. This is called currying, and it's also covered in the elm guide

like image 129
Daenyth Avatar answered Nov 07 '22 17:11

Daenyth


Just to clarify a bit more the second part:

All functions are curried, meaning that update: Msg->Model->Model can receive a Msg and return a function Model->Model or receive a Msg and a Model and return a Model.

In reality, when you call update aMessage aModel you are really calling update aMessage which returns a function and then you pass aModel to that function which will run the expressions in the body of the function and return the updated model.

The arrow is just part of the case.. of syntax. Left side is the pattern you want to match, right side is the expression you wan to execute. In your case, your update will execute the expression only if the Msg was created using the Change constructor.

type Msg
  = Change String | Delete

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }
    Delete ->
      { model | content = "" }

In the previous case, Msg can be constructed either with Change String or with Delete. The update function behaves differently according to the way the msg was constructed.

like image 3
afcastano Avatar answered Nov 07 '22 19:11

afcastano