Search code examples
monadselmfrp

StartApp's Model and Effects in Elm


Say I have some model, action set, and update function as follows:

type alias Model = Int
type Action = Succ

update : Action
      -> Model
      -> (Model, Effects Action)
update action model =
  case action of
    Succ ->
      ( model+1
      , Effects.task <| Task.succeed Succ
      )

This will obviously spin an infinite loop into hades, but I need to know a crucial detail: Will the action sparked by the task see the model+1 version (such that this task sparks the "next" model), or will it be run in parallel to the current model version, model? Essentially, will StartApp store the model in the left of the tuple before running the effects to get the new Action?

The reason I ask this, is from the logs I'm getting from this simple debouncer I've been writing: http://lpaste.net/160866

When I'm using this module, I'm specifically setting debounceBounce = True in the model when I spark the loop:

type alias AppModel =
  { appDebouncer : DebounceModel
  }

type AppAction
  = DebounceAction DebounceAction
  | Finished
  | Start


updateAppAction : AppAction
               -> AppModel
               -> (AppModel, Effects AppAction)
updateAppAction action model =
  case action of
    DebounceAction a ->
      let (newDebounce, eff) =
            updateDebounce Finished a model.appDebounce
      in  ( { model | appDebounce = newDebounce }
          , Effects.tick (handleContinue DebounceAction) eff
          )
    Start ->
      ( { model | appDebounce =
                    let debouncer = model.appDebounce
                    in  { debouncer | debounceBounce = True }
        }
      , Effects.tick (DebounceAction << Tick)
      )
    -- ...

I've found many logs on my machine that specifically shows that the initial model in the loop does not have debounceBounce = True set. Is there a clear reason for this?


Solution

  • Will the action sparked by the task see the model+1 version (such that this task sparks the "next" model), or will it be run in parallel to the current model version, model?

    Yes, the effects act upon the updated model. In the source of StartApp you can see that both the model and Effects are bundled together in a tuple that is fed into foldp. When you use StartApp, you tie every model update and signal into that single foldp, so you are guaranteed there are no race conditions.