elmish


Program

Core abstractions for creating and running the dispatch loop.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
namespace Elmish


/// Program type captures various aspects of program behavior
type Program<'arg, 'model, 'msg, 'view> = private {
    init : 'arg -> 'model * Cmd<'msg>
    update : 'msg -> 'model -> 'model * Cmd<'msg>
    subscribe : 'model -> Cmd<'msg>
    view : 'model -> Dispatch<'msg> -> 'view
    setState : 'model -> Dispatch<'msg> -> unit
    onError : (string*exn) -> unit
    syncDispatch: Dispatch<'msg> -> Dispatch<'msg>
}

/// Program module - functions to manipulate program instances
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Program =
    /// Typical program, new commands are produced by `init` and `update` along with the new state.
    let mkProgram 
        (init : 'arg -> 'model * Cmd<'msg>) 
        (update : 'msg -> 'model -> 'model * Cmd<'msg>)
        (view : 'model -> Dispatch<'msg> -> 'view) =
        { init = init
          update = update
          view = view
          setState = fun model -> view model >> ignore
          subscribe = fun _ -> Cmd.none
          onError = Log.onError
          syncDispatch = id }

    /// Simple program that produces only new state with `init` and `update`.
    let mkSimple 
        (init : 'arg -> 'model) 
        (update : 'msg -> 'model -> 'model)
        (view : 'model -> Dispatch<'msg> -> 'view) =
        { init = init >> fun state -> state,Cmd.none
          update = fun msg -> update msg >> fun state -> state,Cmd.none
          view = view
          setState = fun model -> view model >> ignore
          subscribe = fun _ -> Cmd.none
          onError = Log.onError
          syncDispatch = id }

    /// Subscribe to external source of events.
    /// The subscription is called once - with the initial model, but can dispatch new messages at any time.
    let withSubscription (subscribe : 'model -> Cmd<'msg>) (program: Program<'arg, 'model, 'msg, 'view>) =
        let sub model =
            Cmd.batch [ program.subscribe model
                        subscribe model ]
        { program with subscribe = sub }

    /// Trace all the updates to the console
    let withConsoleTrace (program: Program<'arg, 'model, 'msg, 'view>) =
        let traceInit (arg:'arg) =
            let initModel,cmd = program.init arg
            Log.toConsole ("Initial state:", initModel)
            initModel,cmd

        let traceUpdate msg model =
            Log.toConsole ("New message:", msg)
            let newModel,cmd = program.update msg model
            Log.toConsole ("Updated state:", newModel)
            newModel,cmd

        { program with
            init = traceInit 
            update = traceUpdate }

    /// Trace all the messages as they update the model
    let withTrace trace (program: Program<'arg, 'model, 'msg, 'view>) =
        let update msg model =
            let state,cmd = program.update msg model
            trace msg state
            state,cmd
        { program
            with update = update }

    /// Handle dispatch loop exceptions
    let withErrorHandler onError (program: Program<'arg, 'model, 'msg, 'view>) =
        { program
            with onError = onError }

    /// For library authors only: map existing error handler and return new `Program` 
    let mapErrorHandler map (program: Program<'arg, 'model, 'msg, 'view>) =
        { program
            with onError = map program.onError }

    /// For library authors only: get the current error handler 
    let onError (program: Program<'arg, 'model, 'msg, 'view>) =
        program.onError

    /// For library authors only: function to render the view with the latest state 
    let withSetState (setState:'model -> Dispatch<'msg> -> unit)
                     (program: Program<'arg, 'model, 'msg, 'view>) =        
        { program
            with setState = setState }

    /// For library authors only: return the function to render the state 
    let setState (program: Program<'arg, 'model, 'msg, 'view>) =        
        program.setState

    /// For library authors only: return the view function 
    let view (program: Program<'arg, 'model, 'msg, 'view>) =        
        program.view

    /// For library authors only: function to synchronize the dispatch function
    let withSyncDispatch (syncDispatch:Dispatch<'msg> -> Dispatch<'msg>)
                         (program: Program<'arg, 'model, 'msg, 'view>) =        
        { program
            with syncDispatch = syncDispatch }

    /// For library authors only: map the program type
    let map mapInit mapUpdate mapView mapSetState mapSubscribe
            (program: Program<'arg, 'model, 'msg, 'view>) =
        { init = mapInit program.init
          update = mapUpdate program.update
          view = mapView program.view
          setState = mapSetState program.setState
          subscribe = mapSubscribe program.subscribe
          onError = program.onError
          syncDispatch = id }

    /// Start the program loop.
    /// arg: argument to pass to the init() function.
    /// program: program created with 'mkSimple' or 'mkProgram'.
    let runWith (arg: 'arg) (program: Program<'arg, 'model, 'msg, 'view>) =
        let (model,cmd) = program.init arg
        let rb = RingBuffer 10
        let mutable reentered = false
        let mutable state = model        
        let rec dispatch msg = 
            if reentered then
                rb.Push msg
            else
                reentered <- true
                let mutable nextMsg = Some msg
                while Option.isSome nextMsg do
                    let msg = nextMsg.Value
                    try
                        let (model',cmd') = program.update msg state
                        program.setState model' syncDispatch
                        cmd' |> Cmd.exec syncDispatch
                        state <- model'
                    with ex ->
                        program.onError (sprintf "Unable to process the message: %A" msg, ex)
                    nextMsg <- rb.Pop()
                reentered <- false
        and syncDispatch = program.syncDispatch dispatch            

        program.setState model syncDispatch
        let sub = 
            try 
                program.subscribe model 
            with ex ->
                program.onError ("Unable to subscribe:", ex)
                Cmd.none
        sub @ cmd |> Cmd.exec syncDispatch

    /// Start the dispatch loop with `unit` for the init() function.
    let run (program: Program<unit, 'model, 'msg, 'view>) = runWith () program
Program.init: 'arg -> 'model * obj
Program.update: 'msg -> 'model -> 'model * obj
Program.subscribe: 'model -> obj
Program.view: 'model -> obj -> 'view
Program.setState: 'model -> obj -> unit
type unit = Unit
Program.onError: string * exn -> unit
Multiple items
val string : value:'T -> string

--------------------
type string = System.String
type exn = System.Exception
Program.syncDispatch: obj -> obj
Multiple items
type RequireQualifiedAccessAttribute =
  inherit Attribute
  new : unit -> RequireQualifiedAccessAttribute

--------------------
new : unit -> RequireQualifiedAccessAttribute
Multiple items
type CompilationRepresentationAttribute =
  inherit Attribute
  new : flags:CompilationRepresentationFlags -> CompilationRepresentationAttribute
  member Flags : CompilationRepresentationFlags

--------------------
new : flags:CompilationRepresentationFlags -> CompilationRepresentationAttribute
type CompilationRepresentationFlags =
  | None = 0
  | Static = 1
  | Instance = 2
  | ModuleSuffix = 4
  | UseNullAsTrueValue = 8
  | Event = 16
CompilationRepresentationFlags.ModuleSuffix: CompilationRepresentationFlags = 4
Multiple items
module Program

from Elmish


 Program module - functions to manipulate program instances


--------------------
type Program<'arg,'model,'msg,'view> =
  private {init: 'arg -> 'model * obj;
           update: 'msg -> 'model -> 'model * obj;
           subscribe: 'model -> obj;
           view: 'model -> obj -> 'view;
           setState: 'model -> obj -> unit;
           onError: string * exn -> unit;
           syncDispatch: obj -> obj;}


 Program type captures various aspects of program behavior
val mkProgram : init:('arg -> 'model * obj) -> update:('msg -> 'model -> 'model * obj) -> view:('model -> obj -> 'view) -> Program<'arg,'model,'msg,'view>


 Typical program, new commands are produced by `init` and `update` along with the new state.
val init : ('arg -> 'model * obj)
val update : ('msg -> 'model -> 'model * obj)
val view : ('model -> obj -> 'view)
val model : 'model
val ignore : value:'T -> unit
val id : x:'T -> 'T
val mkSimple : init:('arg -> 'model) -> update:('msg -> 'model -> 'model) -> view:('model -> obj -> 'view) -> Program<'arg,'model,'msg,'view>


 Simple program that produces only new state with `init` and `update`.
val init : ('arg -> 'model)
val update : ('msg -> 'model -> 'model)
val state : 'model
val msg : 'msg
val withSubscription : subscribe:('model -> 'a) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 Subscribe to external source of events.
 The subscription is called once - with the initial model, but can dispatch new messages at any time.
val subscribe : ('model -> 'a)
val program : Program<'arg,'model,'msg,'view>
type Program<'arg,'model,'msg,'view> =
  private {init: 'arg -> 'model * obj;
           update: 'msg -> 'model -> 'model * obj;
           subscribe: 'model -> obj;
           view: 'model -> obj -> 'view;
           setState: 'model -> obj -> unit;
           onError: string * exn -> unit;
           syncDispatch: obj -> obj;}


 Program type captures various aspects of program behavior
val sub : ('b -> 'c)
val model : 'b
val withConsoleTrace : program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 Trace all the updates to the console
val traceInit : ('arg -> 'model * obj)
val arg : 'arg
val initModel : 'model
val cmd : obj
val traceUpdate : ('msg -> 'model -> 'model * obj)
val newModel : 'model
val withTrace : trace:('msg -> 'model -> unit) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 Trace all the messages as they update the model
val trace : ('msg -> 'model -> unit)
val withErrorHandler : onError:(string * exn -> unit) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 Handle dispatch loop exceptions
val onError : (string * exn -> unit)
val mapErrorHandler : map:((string * exn -> unit) -> string * exn -> unit) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 For library authors only: map existing error handler and return new `Program`
val map : ((string * exn -> unit) -> string * exn -> unit)
val onError : program:Program<'arg,'model,'msg,'view> -> (string * exn -> unit)


 For library authors only: get the current error handler
val withSetState : setState:('model -> obj -> unit) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 For library authors only: function to render the view with the latest state
val setState : ('model -> obj -> unit)
val setState : program:Program<'arg,'model,'msg,'view> -> ('model -> obj -> unit)


 For library authors only: return the function to render the state
val view : program:Program<'arg,'model,'msg,'view> -> ('model -> obj -> 'view)


 For library authors only: return the view function
val withSyncDispatch : syncDispatch:(obj -> obj) -> program:Program<'arg,'model,'msg,'view> -> Program<'arg,'model,'msg,'view>


 For library authors only: function to synchronize the dispatch function
val syncDispatch : (obj -> obj)
val map : mapInit:(('arg -> 'model * obj) -> 'a -> 'b * obj) -> mapUpdate:(('msg -> 'model -> 'model * obj) -> 'c -> 'b -> 'b * obj) -> mapView:(('model -> obj -> 'view) -> 'b -> obj -> 'd) -> mapSetState:(('model -> obj -> unit) -> 'b -> obj -> unit) -> mapSubscribe:(('model -> obj) -> 'b -> obj) -> program:Program<'arg,'model,'msg,'view> -> Program<'a,'b,'c,'d>


 For library authors only: map the program type
val mapInit : (('arg -> 'model * obj) -> 'a -> 'b * obj)
val mapUpdate : (('msg -> 'model -> 'model * obj) -> 'c -> 'b -> 'b * obj)
val mapView : (('model -> obj -> 'view) -> 'b -> obj -> 'd)
val mapSetState : (('model -> obj -> unit) -> 'b -> obj -> unit)
val mapSubscribe : (('model -> obj) -> 'b -> obj)
val runWith : arg:'arg -> program:Program<'arg,'model,'msg,'view> -> 'a


 Start the program loop.
 arg: argument to pass to the init() function.
 program: program created with 'mkSimple' or 'mkProgram'.
val rb : obj
val mutable reentered : bool
val mutable state : 'model
val dispatch : ('msg -> unit)
val mutable nextMsg : 'msg option
union case Option.Some: Value: 'T -> Option<'T>
module Option

from Microsoft.FSharp.Core
val isSome : option:'T option -> bool
property Option.Value: 'msg
val model' : 'model
val cmd' : obj
val syncDispatch : obj
val ex : exn
val sprintf : format:Printf.StringFormat<'T> -> 'T
val sub : obj
val run : program:Program<unit,'model,'msg,'view> -> 'a


 Start the dispatch loop with `unit` for the init() function.
val program : Program<unit,'model,'msg,'view>