on e284d1a help sign in
patch/Quickref.md
322 lines 15 kB history raw
1# Reflex / Reflex-Dom Quick(ish) Reference
3## Typeclasses
5Many Reflex functions operate in monadic context `X a`, where the monadic type X supports various additional typeclasses such as MonadWidget, MonadHold, or MonadSample in addition to Monad itself. For Reflex-Dom users, the type X will generally be `Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider))`, from the Reflex-Dom main entry point:
7```haskell
8mainWidget :: Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
9```
11The function signatures here have been simplified by removing many typeclass constraints and adding simple annotations to each function. Also the ubiquitous 't' type parameter has been removed.
13Functions annotated with "[ ]" are *pure*: They operate on Events, Behaviors, or Dynamics uniformly without regard to the "current time".
15Other functions must operate in some monadic context, because they produce a result "as of now". The annotations are:
17```haskell
18[S] -- Function runs in any monad supporting MonadSample
19[H] -- Function runs in any monad supporting MonadHold
20[W] -- Function runs in any monad supporting MonadWidget
21```
23Since MonadWidget depends on MonadHold and MonadHold depends on MonadSample, any [S] function also runs in [H] or [W] context, and any [H] function also runs in [W].
25## Reflex
27### Functions producing Event
29```haskell
30-- Trivial Event
31[ ] never :: Event a
33-- Extract Event from Dynamic
34[ ] updated :: Dynamic a -> Event a
36-- Transform Event to Event using function
37[ ] fmap :: (a -> b) -> Event a -> Event b
38[ ] fmapMaybe :: (a -> Maybe b) -> Event a -> Event b
39[ ] ffilter :: (a -> Bool) -> Event a -> Event a
40[ ] ffor :: Event a -> (a -> b) -> Event b
41[ ] fforMaybe :: Event a -> (a -> Maybe b) -> Event b
43-- Event to identical Event with debug trace.
44[ ] traceEvent :: Show a => String -> Event a -> Event a
45[ ] traceEventWith :: (a -> String) -> Event a -> Event a
47-- Transform Event to Event by sampling Behavior or Dynamic
48[ ] gate :: Behavior Bool -> Event a -> Event a
49[ ] tag :: Behavior a -> Event b -> Event a
50[ ] tagDyn :: Dynamic a -> Event b -> Event a
51[ ] attach :: Behavior a -> Event b -> Event (a, b)
52[ ] attachDyn :: Dynamic a -> Event b -> Event (a, b)
53[ ] attachWith :: (a -> b -> c) -> Behavior a -> Event b -> Event c
54[ ] attachDynWith :: (a -> b -> c) -> Dynamic a -> Event b -> Event c
55[ ] attachWithMaybe :: (a -> b -> Maybe c) -> Behavior a -> Event b -> Event c
56[ ] attachDynWithMaybe :: (a -> b -> Maybe c) -> Dynamic a -> Event b -> Event c
58-- Combine multiple Events
59[ ] <> :: Monoid a => Event a -> Event a -> Event a
60[ ] mergeWith :: (a -> a -> a) -> [Event a] -> Event a
61[ ] leftmost :: [Event a] -> Event a
62[ ] mergeList :: [Event a] -> Event (NonEmpty a)
63[ ] merge :: GCompare k => DMap (WrapArg Event k) -> Event (DMap k)
64[ ] mergeMap :: Ord k => Map k (Event a) -> Event (Map k a)
66-- Efficient one-to-many fanout
67[ ] fanMap :: Ord k => Event (Map k a) -> EventSelector (Const2 k a)
68[ ] fan :: GCompare k => Event (DMap k) -> EventSelector k
69[ ] select :: EventSelector k -> k a -> Event a
71-- Event to Event via monadic function
72[ ] push :: (a -> m (Maybe b)) -> Event a -> Event b
73[ ] pushAlways :: (a -> m b ) -> Event a -> Event b
74 -- Note supplied function operates in [H] context
76-- Event to monadic Event
77[H] headE :: Event a -> m (Event a)
78[H] tailE :: Event a -> m (Event a)
79[H] headTailE :: Event a -> m (Event a, Event a)
80```
82### Functions producing Behavior
84```haskell
85-- Trivial Behavior
86[ ] constant :: a -> Behavior a
88-- Extract Behavior from Dynamic
89[ ] current :: Dynamic a -> Behavior a
91-- Event to monadic Behavior
92[H] hold :: a -> Event a -> m (Behavior a)
94-- Transform Behavior to Behavior using function
95[ ] fmap :: (a -> b) -> Behavior a -> Behavior b
96[ ] ffor :: Behavior a -> (a -> b) -> Behavior b
97[ ] <*> :: Behavior (a -> b) -> Behavior a -> Behavior b
98[ ] >>= :: Behavior a -> (a -> Behavior b) -> Behavior b
99[ ] <> :: Monoid a => Behavior a -> Behavior a -> Behavior a
100-- ... plus many more due to typeclass membership
102-- Behavior to Behavior via monadic value
103[S] sample :: Behavior a -> m a
104[ ] pull :: m a -> Behavior a
105 -- Note supplied value is in [S] context
106```
108### Functions producing Dynamic
110```haskell
111-- Trivial Dynamic
112[ ] constDyn :: a -> Dynamic a
114-- Construct Dynamic from Event
115[H] holdDyn :: a -> Event a -> m (Dynamic a)
116[H] foldDyn :: (a -> b -> b) -> b -> Event a -> m (Dynamic b)
117[H] foldDynM :: (a -> b -> m' b) -> b -> Event a -> m (Dynamic b)
118 -- Note supplied function operates in [H] context
119[H] count :: Num b => Event a -> m (Dynamic b)
120[H] toggle :: Bool -> Event a -> m (Dynamic Bool)
122-- Transform Dynamic to Dynamic using function
123[H] forDyn :: Dynamic a -> (a -> b) -> m (Dynamic b)
124[H] mapDyn :: (a -> b) -> Dynamic a -> m (Dynamic b)
125[H] mapDynM :: (a -> m' b) -> Dynamic a -> m (Dynamic b)
126 -- Note supplied function runs in [S] context
127[H] splitDyn :: Dynamic (a, b) -> m (Dynamic a, Dynamic b)
129-- Combine multiple Dynamics
130[H] mconcatDyn :: Monoid a => [Dynamic a] -> m (Dynamic a)
131[H] distributeDMapOverDyn :: GCompare k => DMap (WrapArg Dynamic k) -> m (Dynamic (DMap k))
132[H] combineDyn :: (a -> b -> c) -> Dynamic a -> Dynamic b -> m (Dynamic c)
134-- Efficient one-to-many fanout
135[ ] demux :: Ord k => Dynamic k -> Demux k
136[H] getDemuxed :: Eq k => Demux k -> k -> m (Dynamic Bool)
138-- Dynamic to Dynamic, removing updates w/o value change
139[ ] nubDyn :: Eq a => Dynamic a -> Dynamic a
141-- Dynamic to identical Dynamic with debug trace.
142[ ] traceDyn :: Show a => String -> Dynamic a -> Dynamic a
143[ ] traceDynWith :: (a -> String) -> Dynamic a -> Dynamic a
144```
146### Flattening functions
148These functions flatten nested types such as Event-of-Event, Behavior-of-Event, Event-of-Behavior etc, removing the outer wrapper.
150For Events, the returned Event fires whenever the latest Event supplied by the wrapper fires. There are differences in how the functions handle *coincidences* -- situations where the old or new Event fires at the same instant that we switch from old to new. In some cases, the output Event tracks the old Event at the instant of switchover, while in other cases it tracks the new Event.
152```haskell
153-- Flatten Event-of-Event to monadic Event. New Event is used immediately.
154[H] switchPromptly :: Event a -> Event (Event a) -> m (Event a)
156-- Flatten Behavior-of-Event to Event. Old Event is used during switchover.
157[ ] switch :: Behavior (Event a) -> Event a
159-- Flatten Dyanmic-of-Event to Event. New Event is used immediately.
160[ ] switchPromptlyDyn :: Dynamic (Event a) -> Event a
162-- Flatten Event-of-Event to Event that fires when both wrapper AND new Event fire.
163[ ] coincidence :: Event (Event a) -> Event a
165-- Flatten Dynamic-of-Dynamic to Dynamic. New Dynamic is used immediately.
166-- Output updated whenever inner OR outer Dynamic updates.
167[ ] joinDyn :: Dynamic (Dynamic a) -> Dynamic a
168[ ] joinDynThroughMap :: Ord k => Dynamic (Map k (Dynamic a)) -> Dynamic (Map k a)
170-- Flatten Event-of-Behavior to monadic Behavior
171[H] switcher :: Behavior a -> Event (Behavior a) -> m (Behavior a)
172```
174## Reflex-Dom
176### Creating widgets (DOM elements hooked into the FRP system)
178#### Basic widgets
180These functions generally take an element tag (such as "div", "h1", etc) and a child widget, and produce a widget of the given type containing the child. Some of these functions return data of type `El`, which is a handle to the created DOM element along with a set of potential Events that might occur on that element.
182Widgets may return any type (this is 'a' in many of the functions below). Often this will be an Event carrying user interactions with the widget.
184```haskell
185-- Simplest form. Create a widget of given type containing the given child.
186-- Return whatever the child returns.
187[W] el :: String -> m a -> m a
189-- This version returns the 'El' as well.
190[W] el' :: String -> m a -> m (El, a)
192-- These two additionally apply attributes to the element, such as ("class" =: "blah")
193[W] elAttr :: String -> Map String String -> m a -> m a
194[W] elAttr' :: String -> Map String String -> m a -> m (El, a)
196-- As above, but now the attribute map is Dynamic
197[W] elDynAttr :: String -> Dynamic (Map String String) -> m a -> m a
198[W] elDynAttr' :: String -> Dynamic (Map String String) -> m a -> m (El, a)
200-- Shortcut for elAttr when you only want to set the "class" attribute.
201[W] elClass :: String -> String -> m a -> m a
203-- Even shorter-cut for above when element type is "div". Create a div of given class.
204[W] divClass :: String -> m a -> m a
206-- Create a widget of given type with arbitrary, Dymamic HTML inside.
207[W] elDynHtml' :: String -> Dynamic String -> m El
208[W] elDynHtmlAttr' :: String -> Map String String -> Dynamic String -> m El
210-- Shortcut for elDynHtml' where the type is "div" and you don't need the 'El'.
211[W] dynHtml :: Dynamic String -> m ()
213-- Create a static text element
214[W] text :: String -> m ()
216-- Create a dynamic text element
217[W] dynText :: Dynamic String -> m ()
218[W] display :: Show a => Dynamic a -> m ()
220-- Create a "button" element with given label, return onClick Event
221[W] button :: String -> m (Event ())
223-- Empty widget
224[W] blank :: m ()
225```
227#### Dynamic widgets
229In the Dynamic cases above, the *content* of a widget is dynamic but the *definition* of the widget is static. The functions below enable the definition and/or structure of the widget itself to change over time.
231Note the "list" functions do not imply particular HTML tags (ul, li, etc), though the widgets they create can have those tags if you construct them appropriately.
233```haskell
234-- Given a Dynamic of widget-creating actions, create a widget that is redefined
235-- whenever the Dynamic updates. The returned Event of widget results occurs when
236-- the Dynamic does. Note that if type 'a' is an Event, the return value is an
237-- Event-of-Events that would typically be flattened.
238[W] dyn :: Dynamic (m a) -> m (Event a)
240-- Same as dyn, but takes initial value and an update Event instead of a Dynamic.
241[W] widgetHold :: m a -> Event (m a) -> m (Dynamic a)
243-- Given a Dynamic key/value map and a function to create a widget for a given
244-- key & Dynamic value, create a bunch of widgets. Widgets will be created,
245-- destroyed, and updated appropriately as the map changes. Returns Dynamic map
246-- from keys to widget results.
247[W] listWithKey :: Ord k =>
248 Dynamic (Map k v) -> (k -> Dynamic v -> m a ) -> m (Dynamic (Map k a))
250-- Same as above where the widget constructor doesn't care about the key.
251[W] list :: Ord k =>
252 Dynamic (Map k v) -> ( Dynamic v -> m a ) -> m (Dynamic (Map k a))
254-- Even simpler version where there are no keys and we just use a list.
255[W] simpleList ::
256 Dynamic [v] -> ( Dynamic v -> m a ) -> m (Dynamic [a])
258-- Like listWithKey specialized for widgets returning (Event a). listWithKey would
259-- return 'Dynamic (Map k (Event a))' in this scenario, but listViewWithKey flattens
260-- this to 'Event (Map k a)' via 'switch'.
261[W] listViewWithKey :: Ord k =>
262 Dynamic (Map k v) -> (k -> Dynamic v -> m (Event a)) -> m (Event (Map k a))
264-- As above, but there is a "current key", and the widget constructor gets a
265-- Dynamic Bool indicating if that widget is currently selected. The returned
266-- Event fires when any of the widgets' returned Events fire, and returns the key
267-- of an arbitrary firing widget.
268[W] selectViewListWithKey_ :: Ord k => Dynamic k ->
269 Dynamic (Map k v) -> (k -> Dynamic v -> Dynamic Bool -> m (Event a)) -> m (Event k)
271-- Same as listWithKey, but takes initial values and an updates Event instead of a Dynamic.
272[W] listWithKey' :: Ord k =>
273 Map k v -> Event (Map k (Maybe v)) -> (k -> v -> Event v -> m a) -> m (Dynamic (Map k a))
275-- tableDynAttr
276-- tabDisplay
277-- workflow
278-- workflowView
279```
281### Connecting to the real world (I/O)
283#### Connecting to DOM events
285```haskell
286-- Extract the specified Event from an 'El'. The allowable event names, and their
287-- corresponding data types, are listed in Reflex/Dom/Widget/Basic.hs
288[ ] domEvent :: EventName en -> El -> Event (EventResultType en)
289```
291#### Performing arbitrary I/O in response to Events
293```haskell
294-- Run side-effecting actions in Event when it occurs; returned Event contains
295-- results. Side effects run in (WidgetHost m) monad, which includes [S] and [H]
296-- and can also do I/O via liftIO
297[W] performEvent :: Event ( WidgetHost m a) -> m (Event a)
299-- Just run side-effects; no return Event
300[W] performEvent_ :: Event ( WidgetHost m ()) -> m ()
302-- Actions run asynchronously; actions are given a callback to send return values
303[W] performEventAsync :: Event ((a -> IO ()) -> WidgetHost m ()) -> m (Event a)
304```
306### Startup
308```haskell
309-- Reflex-Dom entry point. Takes a monadic widget-building action of lengthy
310-- type and turns it into an IO action.
311[I] mainWidget ::
312 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
313[I] mainWidgetWithHead ::
314 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () ->
315 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
316[I] mainWidgetWithCss ::
317 ByteString ->
318 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
320-- One-shot Event that is triggered once all initial widgets are built
321[W] getPostBuild :: m (Event ())
322```