on 00434d7 help sign in
patch/Quickref.md
344 lines 16 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#### Input widgets
229(These could be implemented entirely using the functions above.)
231These widget builders take a configuration record and return a record containing Events or other useful data associated with the created widget (similar to 'El'). The configuration records have default values, so you can just supply 'def'. See Reflex/Dom/Widget/Input.hs for record fields (Lenses are provided).
233look into preventDefault
235```haskell
236-- Text input.
237[W] textInput :: TextInputConfig -> m TextInput
238[ ] textInputGetEnter :: TextInput -> Event ()
239[W] textArea :: TextAreaConfig -> m TextArea
241-- Checkbox. The Bool supplies the initial state.
242[W] checkbox :: Bool -> CheckboxConfig -> m Checkbox
244-- Dropdown with Dynamic options. First argument is initial state.
245[W] dropdown :: (Ord k, Show k, Read k) =>
246 k -> Dynamic (Map k String) -> DropdownConfig k -> m (Dropdown k)
247```
249#### Dynamic widgets
251In the Dynamic cases so far, 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.
253Note 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.
255```haskell
256-- Given a Dynamic of widget-creating actions, create a widget that is redefined
257-- whenever the Dynamic updates. The returned Event of widget results occurs when
258-- the Dynamic does. Note that if type 'a' is an Event, the return value is an
259-- Event-of-Events that would typically be flattened.
260[W] dyn :: Dynamic (m a) -> m (Event a)
262-- Same as dyn, but takes initial value and an update Event instead of a Dynamic.
263[W] widgetHold :: m a -> Event (m a) -> m (Dynamic a)
265-- Given a Dynamic key/value map and a function to create a widget for a given
266-- key & Dynamic value, create a bunch of widgets. Widgets will be created,
267-- destroyed, and updated appropriately as the map changes. Returns Dynamic map
268-- from keys to widget results.
269[W] listWithKey :: Ord k =>
270 Dynamic (Map k v) -> (k -> Dynamic v -> m a ) -> m (Dynamic (Map k a))
272-- Same as above where the widget constructor doesn't care about the key.
273[W] list :: Ord k =>
274 Dynamic (Map k v) -> ( Dynamic v -> m a ) -> m (Dynamic (Map k a))
276-- Even simpler version where there are no keys and we just use a list.
277[W] simpleList ::
278 Dynamic [v] -> ( Dynamic v -> m a ) -> m (Dynamic [a])
280-- Like listWithKey specialized for widgets returning (Event a). listWithKey would
281-- return 'Dynamic (Map k (Event a))' in this scenario, but listViewWithKey flattens
282-- this to 'Event (Map k a)' via 'switch'.
283[W] listViewWithKey :: Ord k =>
284 Dynamic (Map k v) -> (k -> Dynamic v -> m (Event a)) -> m (Event (Map k a))
286-- As above, but there is a "current key", and the widget constructor gets a
287-- Dynamic Bool indicating if that widget is currently selected. The returned
288-- Event fires when any of the widgets' returned Events fire, and returns the key
289-- of an arbitrary firing widget.
290[W] selectViewListWithKey_ :: Ord k => Dynamic k ->
291 Dynamic (Map k v) -> (k -> Dynamic v -> Dynamic Bool -> m (Event a)) -> m (Event k)
293-- Same as listWithKey, but takes initial values and an updates Event instead of a Dynamic.
294[W] listWithKey' :: Ord k =>
295 Map k v -> Event (Map k (Maybe v)) -> (k -> v -> Event v -> m a) -> m (Dynamic (Map k a))
297-- tableDynAttr
298-- tabDisplay
299-- workflow
300-- workflowView
301```
303### Connecting to the real world (I/O)
305#### Connecting to DOM events
307```haskell
308-- Extract the specified Event from an 'El'. The allowable event names, and their
309-- corresponding data types, are listed in Reflex/Dom/Widget/Basic.hs
310[ ] domEvent :: EventName en -> El -> Event (EventResultType en)
311```
313#### Performing arbitrary I/O in response to Events
315```haskell
316-- Run side-effecting actions in Event when it occurs; returned Event contains
317-- results. Side effects run in (WidgetHost m) monad, which includes [S] and [H]
318-- and can also do I/O via liftIO
319[W] performEvent :: Event ( WidgetHost m a) -> m (Event a)
321-- Just run side-effects; no return Event
322[W] performEvent_ :: Event ( WidgetHost m ()) -> m ()
324-- Actions run asynchronously; actions are given a callback to send return values
325[W] performEventAsync :: Event ((a -> IO ()) -> WidgetHost m ()) -> m (Event a)
326```
328### Startup
330```haskell
331-- Reflex-Dom entry point. Takes a monadic widget-building action of lengthy
332-- type and turns it into an IO action.
333[I] mainWidget ::
334 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
335[I] mainWidgetWithHead ::
336 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () ->
337 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
338[I] mainWidgetWithCss ::
339 ByteString ->
340 Widget Spider (Gui Spider (WithWebView SpiderHost) (HostFrame Spider)) () -> IO ()
342-- One-shot Event that is triggered once all initial widgets are built
343[W] getPostBuild :: m (Event ())
344```