33open System.Threading
44open System.Threading .Tasks
55
6- /// Dispatch - feed new message into the processing loop
6+ /// <summary >
7+ /// A function that feeds a new Message into the processing loop.
8+ /// <seealso href =" https://elmish.github.io/elmish/#dispatch-loop " />
9+ /// </summary >
710type Dispatch < 'msg > = 'msg -> unit
811
9- /// Subscription - return immediately, but may schedule dispatch of a message at any time
12+ /// <summary >
13+ /// A function that returns immediately, but may schedule dispatch of one or multiple Messages at any time
14+ /// via its access to a Dispatch function.
15+ /// This is an abstraction over raw Messages passed along to the MVU processing loop
16+ /// necessary to deal with real-world scenarios in which Effect functions may take a while to complete.
17+ /// This models an Elm "side-effect" like in
18+ /// <seealso href =" https://elmish.github.io/elmish/#tasks-and-side-effects " />
19+ /// or
20+ /// <seealso href =" https://elmprogramming.com/side-effects.html " />
21+ /// </summary >
1022type Effect < 'msg > = Dispatch< 'msg> -> unit
1123
12- /// Cmd - container for effects that may produce messages
24+ /// <summary >
25+ /// A list of Effects that may dispatch Messages;
26+ /// the carriers of instructions you issue from the init and update functions.
27+ /// See
28+ /// <seealso href =" https://elmish.github.io/elmish/#commands " />
29+ /// </summary >
1330type Cmd < 'msg > = Effect< 'msg> list
1431
15- /// Cmd module for creating and manipulating commands
32+ /// A module for creating and manipulating Commands
33+ /// with a Command being a list of Message-dispatching Effects you issue from the init and update functions
34+ /// and an Effect being a function with access to a Dispatch function receiving a Message.
1635[<RequireQualifiedAccess>]
1736module Cmd =
1837 /// Execute the commands using the supplied dispatcher
@@ -24,32 +43,48 @@ module Cmd =
2443 with ex ->
2544 onError ex)
2645
27- /// None - no commands, also known as ` [] `
46+ /// No command; an empty list of Message-dispatching Effects equivalent to ` [] ` .
47+ /// For when you don't want to issue a Command.
2848 let none : Cmd < 'msg > = []
2949
30- /// When emitting the message, map to another type
50+ /// <summary >
51+ /// Converts a Command of type 'a into a Command of type 'msg.
52+ /// This is useful for emitting Commands of a uniform type,
53+ /// like when receiving child messages in a parent-child composition scenario. See
54+ /// <seealso href =" https://elmish.github.io/elmish/docs/parent-child.html " />
55+ /// </summary >
3156 let map ( f : 'a -> 'msg ) ( cmd : Cmd < 'a >) : Cmd < 'msg > =
3257 cmd |> List.map( fun g -> ( fun dispatch -> f >> dispatch) >> g)
3358
34- /// Aggregate multiple commands
59+ /// <summary >
60+ /// Concatenates the Effects of multiple Commands into one list.
61+ /// Use for emitting multiple Commands at the same time from the init or update function.
62+ /// E.g. in an parent-child composition scenario:
63+ /// <seealso href =" https://elmish.github.io/elmish/docs/parent-child.html " />
64+ /// </summary >
3565 let batch ( cmds : Cmd < 'msg > list ) : Cmd < 'msg > = List.concat cmds
3666
37- /// Command to call the effect
67+ /// <summary >
68+ /// Returns a command to call a custom Effect function with access to a Dispatch function.
69+ /// Use for example to dispatch status updates or yield partial results from long-running background tasks.
70+ /// </summary >
3871 let ofEffect ( effect : Effect < 'msg >) : Cmd < 'msg > = [ effect ]
3972
40- /// Command to issue a specific message
73+ /// Command to issue a specific message.
74+ /// Wraps the message into the Command structure returned from the update and init functions.
4175 let ofMsg ( msg : 'msg ) : Cmd < 'msg > = [ fun dispatch -> dispatch msg ]
4276
43- /// Command to issue a specific message, only when Option.IsSome = true
77+ /// Command to issue the message from the message option if Option.IsSome
4478 let ofMsgOption ( msg : 'msg option ) : Cmd < 'msg > =
4579 [ fun dispatch ->
4680 match msg with
4781 | None -> ()
4882 | Some msg -> dispatch msg ]
4983
84+ /// Creates Commands from the return values and/or exceptions of simple functions,
85+ /// wrapping the call in a try/with statement. Use this to deal with code that may throw exceptions.
5086 module OfFunc =
51- /// Command to evaluate a simple function and map the result
52- /// into success or error (of exception)
87+ /// Creates a Command to evaluate a simple function and map either the return value or exception to a message
5388 let either ( task : 'a -> _ ) ( arg : 'a ) ( ofSuccess : _ -> 'msg ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
5489 let bind dispatch =
5590 try
@@ -59,7 +94,7 @@ module Cmd =
5994
6095 [ bind ]
6196
62- /// Command to evaluate a simple function and map the success to a message
97+ /// Creates a Command to evaluate a simple function and map the return value to a message
6398 /// discarding any possible error
6499 let perform ( task : 'a -> _ ) ( arg : 'a ) ( ofSuccess : _ -> 'msg ) : Cmd < 'msg > =
65100 let bind dispatch =
@@ -70,7 +105,8 @@ module Cmd =
70105
71106 [ bind ]
72107
73- /// Command to evaluate a simple function and map the error (in case of exception)
108+ /// Creates a Command to evaluate a simple function returning unit
109+ /// and map the error (in case of exception) to a message
74110 let attempt ( task : 'a -> unit ) ( arg : 'a ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
75111 let bind dispatch =
76112 try
@@ -80,6 +116,9 @@ module Cmd =
80116
81117 [ bind ]
82118
119+ /// Internal module for building Commands from the return values or exceptions of Async functions
120+ /// using Async.Catch like an async try/with statement.
121+ /// You'll probably want to use either of the modules OfAsync or OfAsyncImmediate instead of this.
83122 module OfAsyncWith =
84123 /// Command that will evaluate an async block and map the result
85124 /// into success or error (of exception)
@@ -98,6 +137,7 @@ module Cmd =
98137 [ bind >> start ]
99138
100139 /// Command that will evaluate an async block and map the success
140+ /// discarding any possible error
101141 let perform ( start : Async < unit > -> unit ) ( task : 'a -> Async < _ >) ( arg : 'a ) ( ofSuccess : _ -> 'msg ) : Cmd < 'msg > =
102142 let bind dispatch =
103143 async {
@@ -136,6 +176,10 @@ module Cmd =
136176
137177 [ bind >> start ]
138178
179+ /// For building Commands from Async functions queued to be run in the background, started on a thread pool thread using Async.Start.
180+ /// Suitable for long-running or CPU-bound computations where you want to free up the UI thread to remain responsive to do other work.
181+ /// See https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/async#asyncstart
182+ /// and https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/async-padl-revised-v2.pdf page 5.
139183 module OfAsync =
140184 /// Command that will evaluate an async block and map the result
141185 /// into success or error (of exception)
@@ -150,12 +194,18 @@ module Cmd =
150194 let inline attempt ( task : 'a -> Async < _ >) ( arg : 'a ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
151195 OfAsyncWith.attempt Async.Start task arg ofError
152196
197+ /// Command that will evaluate an async block and map the success 'msg
153198 let inline msg ( task : Async < 'msg >) =
154199 OfAsyncWith.perform Async.Start ( fun () -> task) () id
155200
201+ /// Command that will evaluate an async block and map the success 'msg Option.Value if Option.IsSome
156202 let inline msgOption ( task : Async < 'msg option >) =
157203 OfAsyncWith.performOption Async.Start ( fun () -> task) () id
158204
205+ /// For building Commands from Async functions started immediately on the current operating system thread
206+ /// using Async.StartImmediate. This is helpful if you need to update something on the calling thread during the computation.
207+ /// For example if an asynchronous computation must update a UI (such as updating a progress bar).
208+ /// See https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/async#asyncstartimmediate
159209 module OfAsyncImmediate =
160210 /// Command that will evaluate an async block and map the result
161211 /// into success or error (of exception)
@@ -170,21 +220,27 @@ module Cmd =
170220 let inline attempt ( task : 'a -> Async < _ >) ( arg : 'a ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
171221 OfAsyncWith.attempt Async.StartImmediate task arg ofError
172222
223+ /// <summary >
224+ /// For building Commands from executing ("hot") .NET Tasks using Async.AwaitTask.
225+ /// <seealso href =" https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/async#core-concepts " />
226+ /// </summary >
173227 module OfTask =
174- /// Command to call a task and map the results
228+ /// Command to map both the success and possible error result of a Task
175229 let inline either ( task : 'a -> Task < _ >) ( arg : 'a ) ( ofSuccess : _ -> 'msg ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
176230 OfAsync.either ( task >> Async.AwaitTask) arg ofSuccess ofError
177231
178- /// Command to call a task and map the success
232+ /// Command to map the success result of a Task
179233 let inline perform ( task : 'a -> Task < _ >) ( arg : 'a ) ( ofSuccess : _ -> 'msg ) : Cmd < 'msg > =
180234 OfAsync.perform ( task >> Async.AwaitTask) arg ofSuccess
181235
182- /// Command to call a task and map the error
236+ /// Command to map the error of a Task without a success result
183237 let inline attempt ( task : 'a -> #Task ) ( arg : 'a ) ( ofError : _ -> 'msg ) : Cmd < 'msg > =
184238 OfAsync.attempt ( task >> Async.AwaitTask) arg ofError
185239
240+ /// Command to map the success 'msg returned from a Task
186241 let inline msg ( task : Task < 'msg >) = OfAsync.msg( task |> Async.AwaitTask)
187242
243+ /// Command to map the success 'msg Option.Value returned from a Task if Option.IsSome
188244 let inline msgOption ( task : Task < 'msg option >) =
189245 OfAsync.msgOption( task |> Async.AwaitTask)
190246
0 commit comments