Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
[Faculty of Science Information and Computing Sciences] Applied Functional Programming USCS 2015 Atze Dijkstra Department of Information and Computing Sciences Utrecht University July 6-17, 2015 C18. Functional Reactive Programming (FRP) [Faculty of Science Information and Computing Sciences] C18-1 Functional Reactive Programming (FRP) I Pure (functional) programming: value of computation always the same (guarantee of absence of side effect) I Impure, side effectful programming: value of compuation depends on arbitrary ’outside’ influence Middle way: value of computation depends on time: Behavior a = Time→a I I I I Reactive: changes in Behavior a as a result of (reaction on) external Events occurring at a certain Time Functional (1): description of reactive dependencies in a (functional) declarative way Functional (2): implementation runs in a functional language setting (which it need not be) [Faculty of Science Information and Computing Sciences] C18-2 Functional Reactive Programming (FRP) The model in its purest form type Time = ... -- e.g. Int type Behavior a = Time→a -- aka Signal Most libraries also distinguish between continuous time (pulling) behavior and discrete timed (pushing) events type Event a = [(Time, a)] (Conal Elliot, Push-pull functional reactive programming, 2009) [Faculty of Science Information and Computing Sciences] C18-3 Functional Reactive Programming (FRP) The model is just a model, the reality is different... I Implementations leave Time implicit I Don’t implement Event as a stream but as an IO triggered from “outside” I Dependency of output on input is maintained explicitly in a graph I Events trigger recalculation, caching (statefully) only current values I Cached values are returned by Behavior Many different implementations: yampa, fran, reactive, reactive-banana, sodium, elm, elerea, netwire, ... [Faculty of Science Information and Computing Sciences] C18-4 FRP: Events No event occurrence never :: Event a Stop propagation filterJust :: Event (Maybe a)→Event a filterE :: (a→Bool )→Event a→Event a -- derived Combine event occurrences union :: Event a→Event a→Event a Mapping instance Functor Event [Faculty of Science Information and Computing Sciences] C18-5 FRP: Event & Behavior Hold/accumulate initial & subsequent event values stepper :: a→Event a →Behavior a accumE :: a→Event (a→a)→Event a -- derived accumB :: a→Event (a→a)→Behavior a -- derived Snapshot behavior at event occurrence applyE :: Behavior (a→b)→Event a→Event b Lifting instance Applicative Behavior [Faculty of Science Information and Computing Sciences] C18-6 FRP: derived Syntactic sugar (h@i) :: Behavior (a→b)→Event a→Event b -- derived b h@i e = applyE b e (h@) :: Behavior b→Event a→Event b b h@ e = applyE (const h$i b) e -- derived [Faculty of Science Information and Computing Sciences] C18-7 FRP: examples Count arbitrary events counter :: Event a→Event Int counter e = bcounter h@ e where bcounter = accumB 0 $ fmap (\ → (+1)) e Add up event values (like sum) integral :: Int→Event Int→Event Int integral x e = bintegral h@ e where bintegral = accumB x $ fmap (+) e Calling structure declarative specifies network (graph) of event & behavior dependencies [Faculty of Science Information and Computing Sciences] C18-8 FRP: interpretation How do we observe? Use a model for ‘running’ a network type Event a = [Maybe a ] data Behavior a = StepperB ! a (Event a) type Time = Int I Event: stream of values, indexed by Time, Just means event occurrence, Nothing absence I Behavior : continuous observation changing with events never :: Event a never = repeat Nothing (see package reactive-banana) C18-9 [Faculty of Science Information and Computing Sciences] FRP: interpretation union :: Event a→Event a→Event a union (e1) (e2) = zipWith g e1 e2 where g (Just x) (Just ) = Just x -- left biased g (Just x) Nothing = Just x g Nothing (Just y) = Just y g Nothing Nothing = Nothing [Faculty of Science Information and Computing Sciences] C18-10 FRP: interpretation accumE: Function iteration when event happens accumE :: a→Event (a→a)→Event a accumE x ([ ]) = [] accumE x (Nothing : fs) = Nothing : accumE x (fs) accumE x (Just f : fs) = let y = f x in y ‘seq‘ Just y : accumE y (fs) accumB :: a→Event (a→a)→Behavior a accumB acc e = acc ‘StepperB ‘ (accumE acc e) [Faculty of Science Information and Computing Sciences] C18-11 FRP: interpretation Running: feed events interpret :: (Event a→Event b)→[Maybe a ]→[Maybe b ] interpret f e = f (e) testModel0 :: [a ]→(Event a→Event b)→[Maybe b ] testModel0 es f = interpret f $ map Just es testModel = testModel0 [1 . . 8 :: Int ] Examples Maini testModel0 (replicate 8 ()) counter 01234567 Maini testModel (integral 0) 0 1 3 6 10 15 21 28 [Faculty of Science Information and Computing Sciences] C18-12 FRP: Event switching Dynamicity: over time new events arise or disappear switchE :: Event (Moment (Event a)) →Event a switchB :: Behavior a→ Event (Moment (Behavior a))→Behavior a Higher-order Cannot be done arbitrarily as the structure of dependencies changes in concrete implementations Requires therefore a (usually) monadic structure (Moment) ‘between’ first order and higher order events which ’instantiates’ its argument at a certain time [Faculty of Science Information and Computing Sciences] C18-13 FRP & Wx: example Two counters Libraries: wx, reactive-banana, reactive-banana-wx [Faculty of Science Information and Computing Sciences] C18-14 FRP & Wx: example Widget & layout setup main = start $ do f ← frame [text := "Two Counters"] bup ← button f [text := "Up"] bdw ← button f [text := "Down"] bsw ← button f [text := "Switch Counters"] out1 ← staticText f [text := "0"] out2 ← staticText f [text := "0"] set f [layout := margin 10 $ column 5 [row 5 [widget bup, widget bdw, widget bsw], grid 5 5 [[label "First Counter:", widget out1] , [label "Second Counter:", widget out2] [Faculty of Science Information and Computing Sciences] C18-15 FRP & Wx: example Logic expressed in Wx ... c1 ← variable [value := 0] c2 ← variable [value := 0] is1 ← variable [value := True ] set bsw [on command := set is1 [value :∼ not]] set bup [on command := do {f ← get is1 value ; up f (c1, c2, out1, out2)}] set bdw [on command := do {f ← get is1 value ; dw f (c1, c2, out1, out2)}] ... [Faculty of Science Information and Computing Sciences] C18-16 FRP & Wx: example ... where up left (c1, c2, o1, o2) = (if left then upd o1 c1 else upd o2 c2) (+1) dw left (c1, c2, o1, o2) = (if left then upd o1 c1 else upd o2 c2) (+(−1)) upd t c f = do set c [value :∼ f ] v ← get c value set t [text := show v] [Faculty of Science Information and Computing Sciences] C18-17 FRP & Wx: example Logic expressed in FRP style let networkDescription :: ∀t.Frameworks t ⇒ Moment t () networkDescription = do -- externally triggered eup ← event0 bup command edw ← event0 bdw command esw ← event0 bsw command -- FRP network let -- do we act on the left button? is1 :: Behavior t Bool is1 = accumB True $ not h$ esw ... [Faculty of Science Information and Computing Sciences] C18-18 FRP & Wx: example let . . . do . . . let . . . -- joined state of the two counters counters :: Behavior t (Int, Int) counters = accumB (0, 0) $ union ((up h$i is1) h@i eup) ((dw h$i is1) h@i edw) up left (x, y) = if left then (x + 1, y) else (x, y + 1) dw left (x, y) = if left then (x − 1, y) else (x, y − 1) -- externally rendered sink out1 [text :== show ◦ fst h$i counters] sink out2 [text :== show ◦ snd h$i counters] network ← compile networkDescription actuate network [Faculty of Science Information and Computing Sciences] C18-19 FRP: summary Building GUIs with Haskell I With wx, gtk, ... I Imperative I With logic expressed as (functional) reactive network I Immature (still) FRP elsewhere (outside the Haskell universe) I elm: functional language targeting javascript, html, ... I RxJS, Bacon.js: javascript FRP extensions [Faculty of Science Information and Computing Sciences] C18-20