0 | ||| Switching Combinators
 1 | |||
 2 | ||| Switches allow us to dynamically change the structure
 3 | ||| (wiring) of a running network of stream functions.
 4 | ||| Semantically, the react on discrete events, but
 5 | ||| some of the switching primitives in this module use
 6 | ||| the `Either` data type if it allows us to more exactly
 7 | ||| describe the semantics of a switch.
 8 | module Data.MSF.Switch
 9 |
10 | import Data.MSF.Core
11 | import Data.MSF.Event
12 | import Data.MSF.Running
13 | import Data.MSF.Util
14 |
15 | %default total
16 |
17 | --------------------------------------------------------------------------------
18 | --          Immediate Switches
19 | --------------------------------------------------------------------------------
20 |
21 | ||| Produces output of the first MSF until it produces
22 | ||| a `Left`, in which case the event will be used to
23 | ||| create a new MSF, which will be immediately evaluated
24 | ||| and used henceforth.
25 | |||
26 | ||| This is a one-time switch, which is often used to
27 | ||| run an MSF a fixed number of times or until a certain
28 | ||| event occurs, after which the replacement will be used.
29 | |||
30 | ||| Note: It is unsafe to use this in a recursive setting,
31 | |||       as it would allow us to create an infinite loop
32 | |||       of streaming functions, all of which return `Left`s
33 | |||       forever. Luckily, the totality checker will prevent us
34 | |||       from doing this.
35 | export %inline
36 | switchE : MSF m i (Either e o) -> (e -> MSF m i o) -> MSF m i o
37 | switchE = Switch
38 |
39 | ||| Produces output of the given MSF until it fires an event,
40 | ||| in which case a new MSF is created,
41 | ||| which will be evaluated immediately and used henceforth.
42 | |||
43 | ||| This uses `switchE` internally, so all restrictions mentioned
44 | ||| there apply.
45 | export
46 | switch :
47 |      MSF m i (HList [o, Event e])
48 |   -> (e -> MSF m i o)
49 |   -> MSF m i o
50 | switch sf = switchE $ sf >>^ (\[vo,ve] => event (Right vo) Left ve)
51 |
52 | --------------------------------------------------------------------------------
53 | --          Delayed Switches
54 | --------------------------------------------------------------------------------
55 |
56 | rswUtil : HList [o,Event x] -> Either (x,o) o
57 | rswUtil [vo,Ev vx] = Left (vx,vo)
58 | rswUtil [vo,NoEv]  = Right vo
59 |
60 | ||| Produces output of the given MSF until it fires an event,
61 | ||| in which case a new MSF is created,
62 | ||| which will be used in all further evaluation steps.
63 | export
64 | dSwitch : MSF m i (HList [o, Event e]) -> (e -> MSF m i o) -> MSF m i o
65 | dSwitch sf = switch (sf >>> par [id, iPre NoEv])
66 |
67 | --------------------------------------------------------------------------------
68 | --          Recurring Switches
69 | --------------------------------------------------------------------------------
70 |
71 | export %inline
72 | rSwitch : Monad m => MSF m i o -> MSF m (HList [Event $ MSF m i o,i]) o
73 | rSwitch sf =
74 |   feedback sf . arrM $
75 |     \[sf,[ev,vi]] => do
76 |       (vo,sf2) <- step (fromEvent sf ev) vi
77 |       pure [sf2,vo]
78 |
79 | export %inline
80 | drSwitch : Monad m => MSF m i o -> MSF m (HList [Event $ MSF m i o,i]) o
81 | drSwitch sf =
82 |   feedback sf . arrM $
83 |     \[sf,[ev,vi]] => do
84 |       (vo,sf2) <- step sf vi
85 |       pure [fromEvent sf2 ev,vo]
86 |
87 | ||| Produces output of the first MSF until the second
88 | ||| fires an event, in which case a new MSF is created,
89 | ||| which will be used in all futre evaluation cycles.
90 | export
91 | drswitchWhen :
92 |      {auto _ : Monad m}
93 |   -> MSF m i o
94 |   -> MSF m i (Event e)
95 |   -> (e -> MSF m i o)
96 |   -> MSF m i o
97 | drswitchWhen ini es f = fan [es >>^ map f,id] >>> drSwitch ini
98 |