Questions about elm sintax

Hi I have some basic questions about the elm sintax.
As I am not sure what is going on.

So we have this Statement in the Code :

processEvent : InterfaceToHost.BotEvent → State → ( State, InterfaceToHost.BotResponse )

processEvent =

EveOnline.BotFramework.processEvent processEveOnlineBotEvent

The last line look like we are passing a function to a function ?
Whats going on here ?

I see this kind of statment a lot but all the tutorials on elm do not cover this kind of construction.
Or at they do and I have missed some thing.

Which one is evaluate first?
Also the Looks like the function decliration is asking for InterfaceToHost.BotEvent and a State.
but when calling the funciton you dont pass any variables “processEvent ^^Variables ?^^ =.”

Any way some explination at this point would allow me to unravel what is going on through a lot of the other code.

Welcome @OldMan!

Yes, that code is passing a function to another function. And yes, this is very common.

The same functionality can also be expressed in a more verbose way, and this sometimes helps to understand what is going on. Here I have an example from one of my example projects:

First, the way it is expressed in the example project:

processEvent : InterfaceToHost.BotEvent -> State -> ( State, InterfaceToHost.BotResponse )
processEvent =
    EveOnline.AppFramework.processEvent
        { parseAppSettings = parseBotSettings
        , processEvent = processEveOnlineBotEvent
        }

Here is the same functionality with a different syntax:

processEvent : InterfaceToHost.BotEvent -> State -> ( State, InterfaceToHost.BotResponse )
processEvent event stateBefore =
    EveOnline.AppFramework.processEvent
        { parseAppSettings = parseBotSettings
        , processEvent = processEveOnlineBotEvent
        }
        event
        stateBefore

When you pass an argument to a function, you get back a new function that takes one argument less. I see the official elm guide also has the section titled “Function Types” to explain this: Function Types · An Introduction to Elm

In that guide, I also found this part:

So conceptually, every function accepts one argument. It may return another function that accepts one argument. Etc. At some point it will stop returning functions.

The order of evaluation can change at any time because it has no observable effect. The app behaves the same, independent of the order of evaluation.
The behavior of the app only depends on the value returned by the processEvent function.

When your app works with variables, these go into the State part. For example, the State can be a record that contains multiple variables.

The variables in State are the ones updated by the app code. The values from app-settings could also be considered variables. The variables from app-settings come with the event, so you get the new state of the settings with each event. That also means the interface supports changing the app settings during the session.

This week I got around to updating the guide on developing for EVE Online to include this.
This is now explained in the Entry Point - processEvent section here: bots/developing-for-eve-online.md at 56333a44d00364cb9a45558faa6600a26b7212de · Viir/bots · GitHub

I copied this part of the guide below:


Entry Point - processEvent

Each time an event happens, the framework calls the function processEvent. Because of this unique role, we also call it the ‘entry point’.

Let’s look at the structure of this function.

processEvent : InterfaceToHost.AppEvent -> State -> ( State, InterfaceToHost.AppResponse )

In the type annotation above, we can see a type State used twice. This State is specific to each app. Each app can use it’s own State structure, it just have to be the same in all parts of processEvent. The State appears in one parameter for the first time, meaning the function receives a value of type State when it is used. The second time State appears in the part after the last arrow, meaning it is part of the return type. So the function also returns a value of type State (as part of a tuple).

Each time the engine calls the processEvent function, it gives the previous state as the second argument, and receives the new state with the return value. For the first event, the engine takes the State from the initState value. This passing on of the app state is what allows the engine to show you the current state of the app for inspection.

The other types used in the type annotation above are InterfaceToHost.AppEvent and InterfaceToHost.AppResponse. These are the same for each app.

The type of processEvent is not specific to EVE Online. Apps for other games use the same structure. Apps for the EVE Online client use the EveOnline.AppFramework.processEvent function to produce the more general processEvent function. We can see this in the example projects, no matter if the app is a mining bot, ratting bot, or just a monitor that watches local chat and alerts the user when a hostile pilot enters.

Let’s have a closer look at EveOnline.AppFramework.processEvent:

processEvent :
    { parseAppSettings : String -> Result String appSettings
    , processEvent : EveOnline.AppFramework.AppEventContext appSettings -> EveOnline.AppFramework.AppEvent -> appState -> ( appState, EveOnline.AppFramework.AppEventResponse )
    }
    -> InterfaceToHost.AppEvent
    -> EveOnline.AppFramework.StateIncludingFramework appSettings appState
    -> ( EveOnline.AppFramework.StateIncludingFramework appSettings appState, InterfaceToHost.AppResponse )

(In the source code, you might see less of the EveOnline.AppFramework prefixes because they are implicit for the current module. I added them here to clarify the difference between the ones in EveOnline.AppFramework and in InterfaceToHost).

This processEvent function from the framework for EVE Online gives the event and the response a more specific shape, with a structure that is adapted for working with the game client. It works as a wrapper for the event and response types from the InterfaceToHost module. It hides the generic language of the host, so we don’t need to learn about it but instead can focus on the language that is specific to EVE Online.

The function type shown above looks big and unwieldy, and the first thing we do is to divide it into two parts: The first parameter and the rest. The first parameter is what we supply when we build our app. This is a record with fields named parseAppSettings and processEvent.

All the rest describes what we get back after supplying the record for the first parameter. The type of this latter part matches the type constraint for the processEvent function in the BotEngineApp.elm file (Remember, the state can take any shape). So we don’t look closely at the part after the first parameter, we pass it on to the engine.

That leaves only the parseAppSettings and processEvent fields for us to look at.

Here is how the autopilot example bot code uses the framework function to connect the app code to the host:

processEvent : InterfaceToHost.AppEvent -> State -> ( State, InterfaceToHost.AppResponse )
processEvent =
    EveOnline.AppFramework.processEvent
        { processEvent = processEveOnlineBotEvent
        , parseAppSettings = AppSettings.parseAllowOnlyEmpty ()
        }

Using the parseAppSettings field, we describe how to translate from the app settings string given by the user to the settings. The framework invokes the parseAppSettings function every time the user changes the app-settings. The return type is a kind of Result which means we can decide that a given app-settings string is invalid and reject it. The Err case uses the String type, and we use this to explain to the user what exactly is wrong with the given app-settings string. You don’t need to worry about how to generate these error messages, because there is already a framework for this. In our app, we only need to define a list of valid settings, and the framework will generate a precise error message if the user misspells the name of a setting or tries to use a setting with an unsupported value.

Most of the development activity happens in the function that we give to the processEvent field:

processEvent : EveOnline.AppFramework.AppEventContext appSettings -> EveOnline.AppFramework.AppEvent -> appState -> ( appState, EveOnline.AppFramework.AppEventResponse )

I will quickly break down the Elm syntax here: The part after the last arrow (->) is the return type. It describes the shape of values returned by the app to the framework. The part between the colon (:) and the return type is the list of parameters. So this function has three parameters.

Let’s have a closer look at the parameters:

  • EveOnline.AppFramework.AppEvent: This describes an event that happens during the operation of the app.
  • BotState: The BotState type is specific to the app. With this type, we describe what the app remembers between events. When the framework informs the app about a new event, it also passes the BotState value which the app returned after processing the previous event. But what if this is the first event? Then there is no previous event? In this case, the framework takes the value from the function initState.

All information the app ever receives is coming through the values given with the first and second parameter (AppEventContext and AppEvent).

Just like the structure of the BotState type, its name is also specific for the app. We could as well use another name, as long as we use it consistently in both the last parameter and the return type.