How I write purescript apps
On Thu, 25 Jan 2024, by @lucasdicioccio, 314 words, 0 code snippets, 0 links, 0images.
This article is still considered unfinished and content may change significantly.
-
apps
- main that corresponds to a JS inclusion in html
- copy-to-clipboard actions
- console-logging
- analytics
-
pages
- tracer
- state management
- discussed later, but key is to split ui, core, and other
- action
- traced-wrapper handler
- handler
- handling
- handler-modules
- how ui updates influence core-model updates
- render
- huge pile of rendering functions
- render-modules
- basically copy-pastable chunks of render-function (can refer to actions, state, but not slots)
-
components
- for annoying state (echarts)
- for one-off non-trivial states reducible to few business-wide events (e.g., configuration wizards)
-
bricks
- typical UI mostly concerns (a button, a search-bar)
- state is passed in
- consume a brick handler by passing directly (i.e., you import the brick more than you adapt the brick)
-
widgets
- bricks that start to get tuned to your domain (e.g., a postgrest-endpoint-search bar)
- can define some Action to reduce amount of
onFoo
handlers and incitate contramapping handling- if instantiable/higher-level widget: consider giving an
Action -> action
rather than definingonAction
- if instantiable/higher-level widget: consider giving an
- consume a widget with a mapping function
-
state management
- ui-state vs. core-state vs. storable state
- ECS-flavored style
- seqnums entities
- use
List.Cons (updatedItem) (List.filter (not oldItem) state.entities)
-
code style
- be monotonous
- almost always pass params for nesting, even if redundant
render_section_item state section item
- rely on qualified imports
- bricks should take a
Props
in, should have arender
- almost always pass params for nesting, even if redundant
- exception can happen to split non-trivial logic (e.g.
render
vsrender_box_content
) - use contramapping in Action poppups
- Action tree nesting should reflect the pages/rendering/widgets/bricks nesting
- use utility functor wrapper, really useful in a web-environment to speak about
- a
Remote value
(could be loading, carry api errors) - some
Historical value
(could be current or old value) - an
Historized value
(snapshotted history of values to got back in time)
- a
- do not tie these wrappers to some api-fetching (i.e., it’s normal to build your own Remote value)
- be monotonous
-
example in postgrest-table
- ui state
- core state
- datasets
List { value :: Remote Json, seqnum :: Seqnum "dataset", perspective :: Seqnum "perspective" }
- ajax calls
List { value :: Historical Blob, seqnum :: Seqnum "ajax-call", perspective ...}
- datasets
- storable state
- endpoints
- perspectives
- projections
-
things that are natural
- noop action type, somewhat double use for unimplemented, but also to suppress a handler (alas needed when we want a brick to pick only valid-values but the enclosed html allows invalid events, e.g., parsing a decimal)
- comap comap comap