webbhuset / elm-actor-model / Webbhuset.ActorSystem


type alias PID =
Webbhuset.Internal.PID.PID

A PID is an identifier for a Process.

Build and Initialize the System

element : { init : flags -> SysMsg name appMsg, spawn : name -> PID -> ( appModel, SysMsg name appMsg ), apply : appModel -> AppliedActor appModel output (SysMsg name appMsg), view : List output -> Html (SysMsg name appMsg), onDebug : Error name appMsg -> SysMsg name appMsg } -> Platform.Program flags (Model name appModel) (SysMsg name appMsg)

Create a Browser.element from your Actor System

application : { init : flags -> Url -> Browser.Navigation.Key -> SysMsg name appMsg, spawn : name -> PID -> ( appModel, SysMsg name appMsg ), apply : appModel -> AppliedActor appModel output (SysMsg name appMsg), view : List output -> Html (SysMsg name appMsg), onUrlRequest : Browser.UrlRequest -> SysMsg name appMsg, onUrlChange : Url -> SysMsg name appMsg, onDebug : Error name appMsg -> SysMsg name appMsg } -> Platform.Program flags (Model name appModel) (SysMsg name appMsg)

Create a Browser.application from your Actor System

System Messages

none : SysMsg name appMsg

Don't send or do anything.

Similar concept to Cmd.none

batch : List (SysMsg name appMsg) -> SysMsg name appMsg

Batch control messages

Similar concept to Cmd.batch

Processes

Actors can be spawned (instantiated or started). A spawned actor is called Process. A process is referenced by its PID.

Knowing an Actor's PID you can send messages to it or kill it.

spawn : name -> (PID -> SysMsg name appMsg) -> SysMsg name appMsg

Start an Actor. This will create a process. The PID will be sent in a message using the provied message constructor.

The new process will become a child process of the process that sent the spawn message. This relationship is used when a process is killed.

Example - Actor/PageLayout.elm:

System.spawn
    ActorName.LoginForm
    (\spawnedPID ->
        PageLayout.SetContent spawnedPID
            |> Msg.PageLayout
            |> System.sendToPID pageLayoutPID
    )

In this case the LoginForm will be a child of PageLayout. If PageLayout is killed the LoginForm will also be killed.

sendToPID : PID -> appMsg -> SysMsg name appMsg

Send a message to a Process.

If the target process does not exists the sender component will receive the PIDNotFound system event. (onSystem).

kill : PID -> SysMsg name appMsg

Kill a process. This will also kill all the child processes by default. See Webbhuset.Component.SystemEvent.

Singleton processes can not be killed. Attempts to do so will be ignored.

Singleton Processes

It can be helpful to treat some actors as a singleton process. They are started on application init and will always be running. Some examples are the Router actor or the Navigation. It does not make much sense having multiple of them either.

A singleton process is just a normal actor that you can reference by its name instead of its PID.

spawnSingleton : name -> SysMsg name appMsg

Spawn a singleton process.

sendToSingleton : name -> appMsg -> SysMsg name appMsg

Send a message to a Singleton Process

withSingletonPID : name -> (PID -> SysMsg name appMsg) -> SysMsg name appMsg

Do something with a singleton PID.

Sometimes you want to send a singleton PID to a process.

For example, add the root layout component to the system output.

init flags =
    [ System.withSingletonPID ActorName.PageLayout System.addView
    ]

Another example, you want to treat the site Header as a singleton which makes it easier to send messages to it.

System.withSingletonPID
    ActorName.Header
    (\pid ->
        PageLayout.SetHeader pid
            |> Msg.PageLayout
            |> System.sendToSingleton ActorName.PageLayout
    )

Program Output

You Elm program's Html output (view function) is controlled here. You need to add at least one process to actually see anything more than just a blank page.

addView : PID -> SysMsg name appMsg

Add a process to the global output.

setDocumentTitle : String -> SysMsg name appMsg

Set the document title. Only works with System.application

Debug logging


type Error name appMsg
    = UnmappedInMsgFor name appMsg
    | Bug String

Developer errors

Bootstrap

Don't worry about these for now.


type AppliedActor appModel output msg

An actor after the model has been applied


type alias Actor compModel appModel output msg =
{ init : PID -> ( appModel
, msg )
, update : compModel -> msg -> PID -> ( appModel
, msg )
, view : compModel -> PID -> (PID -> Maybe output) -> output
, onSystem : Webbhuset.Component.SystemEvent.SystemEvent -> PID -> Webbhuset.Component.SystemEvent.Handling msg
, subs : compModel -> PID -> Platform.Sub.Sub msg 
}

An actor is a component that is configured to be part of the system.


type Model name appModel

The Global Model


type alias SysMsg name appMsg =
Webbhuset.Internal.Msg.Msg name appMsg

Your Elm Program will have this as its Msg type.

applyModel : Actor compModel appModel output msg -> compModel -> AppliedActor appModel output msg

Apply the compModel to an actor.