4 ms·
Purescript-Concur is simpler, and allows you to use elm-architecture as well, but also allows you to use your existing functional programming toolkit to the ful
by haskman 5y ago
Purescript-Concur is simpler, and allows you to use elm-architecture as well, but also allows you to use your existing functional programming toolkit to the fullest. It also has react bindings - https://github.com/purescript-concur/purescript-concur-react https://github.com/purescript-concur/purescript-concur-react.
Here's what a counter example looks like -
counter count = do
button [onClick] [text (show count)]
counter (count + 1)
Check out a comparison with elm-architecture at https://ajnsit.github.io/concur-documentation/ch03-01-replicating-elm-architecture.html https://ajnsit.github.io/concur-documentation/ch03-01-replic....
- dorian-graph 5y agoThat Elm comparison is so nice. I felt like half the time I was writing Elm, it was spent on the manual work of the things described in there.
- haskman 5y agoThank you! All the manual wiring in Elm can be very frustrating! Also not having to expose all the action datatypes when they are only being used in a single place can really improve code structure.
- DylanSp 5y agoTwo questions that I didn't see answered in the docs: - How do I manage state that isn't local to one widget? A counter's nice and local, but I don't see how application-wide state gets handled. - How are data fetching and other asynchronous actions wired in?
- dwhitney 5y agoI was wondering that myself. Here's an Ajax example: https://github.com/purescript-concur/purescript-concur-react/blob/master/examples/src/Test/Ajax.purs https://github.com/purescript-concur/purescript-concur-react... It could use some type signatures, but it makes sense. As for managing state, my understanding of the Elm Architecture is that there is one "global" state data structure, and various parts of it are handed down from parent to child. So my question would be the opposite of yours: what if I want local state? Is that possible? There are situations where some toggle being on or off isn't very important and keeping track of it in a global data structure is burdensome
- haskman 5y agoWell elm architecture is just a pattern in Concur. You don't need to store things globally at all. Currently the only thing to take care of is - when a child widget returns some value to the parent, if you want to reinvoke the child widget and somehow restore the previous local state of the child widget, you need to have sent that local state out to the parent previously. This means that you either add the local state to the child widget's return value, or use something like a wire to directly send the state to the parent or something else. I am working on adding automatically persisted local state to Concur which would greatly simplify this. It would provide an API similar to hooks' useState (and the react bindings will actually use hooks for this).
- haskman 5y ago1. Application wide state is easy since you can always access state from parent components in child components. The problem occurs when you want to update parent state from child components. Fortunately, you can make your own abstractions in Concur. For example, you can use a "Wire" - which lets multiple child components share and update parts of the parent's state (https://github.com/purescript-concur/purescript-concur-core/blob/master/src/Concur/Core/Patterns.purs#L117 https://github.com/purescript-concur/purescript-concur-core/...). Note how this abstraction just uses the high level Concur API, and doesn't depend on the UI backend. With a wire the code might look something like this - -- A wire into parent's state, accessible using `with`, and updateable using `wire.send` counter wire = with wire \i -> do button [onClick] [text (show i)] wire.send (i+1) And you can compose several counters that share state like this (the first two counters will increment together - -- Parent component creates a wire using `local` and an initial value local 0 \w -> div [] [ counter w , counter w , some , other , widgets ] -- Beyond this point the local state is gone and can't be accessed doSomethingElse 2. Concur widgets can perform sync effect as well as async effects using `liftEffect` and `liftAffect`, and the results of those actions are available within the monad just like other widget results. Does that answer your question?