1
votes

I am not able grasp the following function declaration & definition syntax of elm language.

keyDown: (Int -> Msg) -> Attribute msg
keyDown event = 
  on "keydown" (Json.map event keyCode)

What does the first line means? keyDown: (Int -> Msg) -> Attribute msg. Does it means, that the keyDown function takes, Int & Msg type params & returns of type Attribute?

What exactly happens in the function definition part?

How the parameters to the function are defined?

1

1 Answers

4
votes

TL;DR

keyDown function accepts another function as an argument and returns an attribute, which Elm's renderer uses to attach an event listener.

If you define a type

type Msg
    = KeyDown Int

The KeyDown acts as a constructor function for values of type Msg, so we can say that the implicit type of it is KeyDown: Int -> Msg, which is what you want when you want to retrieve a key code from a DOM Event.

Explanation

First of all, I must say that the proper implementation should look like this:

keyDown : (Int -> msg) -> Attribute msg
keyDown tagger =
    on "keydown" (Json.Decode.map tagger keyCode)

It is important to have msg type variable in the signature, so it's possible to use this event listener in different parts of the application, where Html emits different types of msg

To understand what is happening here, let's look closer at Html.Events.on

on : String -> Decoder msg -> Attribute msg

Every DOM event is represented as a JavaScript object with certain fields. To retrieve the data from JavaScript, Elm needs to pass it through a Decoder to ensure type safety in runtime, just like with HTTP requests.

The decoder in on is expected to produce the same type of message, as the attribute itself.

By default, keyCode decoder decodes an Int value, but what we want is to emit some message.

That's where Json.Decode.map helps us to get the Int and apply some tagger function, which produces a message.

Decoder

The entire (Json.map event keyCode) part is essentially a Decoder msg, which is applied to the event object to extract the key code and "tag" it with a message.