-
Notifications
You must be signed in to change notification settings - Fork 1
/
cmd.fs
111 lines (90 loc) · 3.47 KB
/
cmd.fs
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
(*
Copyright 2016 fable-elmish contributors
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
*)
(*
In accordance with the Apache License, Version 2.0, section 4, this is a
notice to inform the recipient that this file has been modified by the
elmish-xamarin-forms contributors.
*)
(**
Cmd
---------
Core abstractions for dispatching messages in Elmish.
*)
namespace Elmish
open System
/// Dispatch - feed new message into the processing loop
type Dispatch<'msg> = 'msg -> unit
/// Subscription - return immediately, but may schedule dispatch of a message at any time
type Sub<'msg> = Dispatch<'msg> -> unit
/// Cmd - container for subscriptions that may produce messages
type Cmd<'msg> = Sub<'msg> list
/// Cmd module for creating and manipulating commands
[<RequireQualifiedAccess>]
module Cmd =
/// None - no commands, also known as `[]`
let none : Cmd<'msg> =
[]
/// Command to issue a specific message
let ofMsg (msg:'msg) : Cmd<'msg> =
[fun dispatch -> dispatch msg]
/// When emitting the message, map to another type
let map (f: 'a -> 'msg) (cmd: Cmd<'a>) : Cmd<'msg> =
cmd |> List.map (fun g -> (fun dispatch -> f >> dispatch) >> g)
/// Aggregate multiple commands
let batch (cmds: #seq<Cmd<'msg>>) : Cmd<'msg> =
cmds |> List.concat
/// Command that will evaluate an async block and map the result
/// into success or error (of exception)
let ofAsync (task: 'a -> Async<_>)
(arg: 'a)
(ofSuccess: _ -> 'msg)
(ofError: _ -> 'msg) : Cmd<'msg> =
let bind dispatch =
async {
let! r = task arg |> Async.Catch
dispatch (match r with
| Choice1Of2 x -> ofSuccess x
| Choice2Of2 x -> ofError x)
}
[bind >> Async.StartImmediate]
/// Command to evaluate a simple function and map the result
/// into success or error (of exception)
let ofFunc (task: 'a -> _) (arg: 'a) (ofSuccess: _ -> 'msg) (ofError: _ -> 'msg) : Cmd<'msg> =
let bind dispatch =
try
task arg
|> (ofSuccess >> dispatch)
with x ->
x |> (ofError >> dispatch)
[bind]
/// Command to evaluate a simple function and map the success to a message
/// discarding any possible error
let performFunc (task: 'a -> _) (arg: 'a) (ofSuccess: _ -> 'msg) : Cmd<'msg> =
let bind dispatch =
try
task arg
|> (ofSuccess >> dispatch)
with x ->
()
[bind]
/// Command to evaluate a simple function and map the error (in case of exception)
let attemptFunc (task: 'a -> unit) (arg: 'a) (ofError: _ -> 'msg) : Cmd<'msg> =
let bind dispatch =
try
task arg
with x ->
x |> (ofError >> dispatch)
[bind]
/// Command to call the subscriber
let ofSub (sub: Sub<'msg>) : Cmd<'msg> =
[sub]