Flame: A PureScript front-end framework inspired by the Elm architecture
github.com
github.com
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-replic....Also not having to expose all the action datatypes when they are only being used in a single place can really improve code structure.
- 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?
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
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).
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/...). 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?- I can't have Sets of arbitrary Types they must be `comparable`. I cannot create a custom comparable type.
- Records, Bool and custom Union Types are not `comparable`
- Bool and Simple Union Types could have been comparable if their comparison worked like they were Enumerated Types. Elm does not have Enumerated types.
Basically https://github.com/elm/compiler/issues/1008 made me look for better alternatives.
ReScript + rescript-react is a good alternative. Less safe, waaaay more verbose; but backed by Facebook.
This is quite cute (in TypeScript though): https://github.com/cyclejs/cyclejs
And Yew is super cool, it goes the WASM route (in Rust): https://github.com/yewstack/yew
was, methinks, the salient part of his point.
(I emphasize, I too think Elm is coherent enough so you understand how it works, which other Javascript frameworks lack.)
Looks like purescript development requires node, purescipt compiler, and spago build tool. I have set these up. In future I'll try to learn Flame framework and then adapt my elm code to this.
The fact that Dhall’s aesthetics mirror those of PureScript (including Unicode) is a cherry on top.
All trade offs.
Either you accept the walls or you go with PureScript (which could be described as "Elm without the walls"; but then there is a lot more to learn and a whole plethora of frameworks where Elm has the one-to-rule-m-all-FW baked in).
Also, Evan has not closed this issue since 2015. Most probably it is about "too much work to get it right" rather than "I'm not convinced that we need it".
With comparability you can use the operators (<,>,<=,>=,==,/=,etc.) on various types. This is not how Elm usually works. I.e. the `map` function is different for `List.map`, `Dict.map`, `Maybe.map`, etc.
In Haskell and PS you have type classes. Some types can be mapped, some can be compared, etc. Then the type class defines what functions should be implemented for such type in order to be part of the type class.
You think it's a small change, but it is pretty much what sets Elm and PS apart. Errors can also get a lot more complex with code that leans heavily on type classes.
As in Elm, I’ve never fully understood why the events emit a value of some message type that gets interpreted into a function from ‘state -> state’ instead of handling with a state transformation directly.
Feels like boilerplate to me. I can see situations where this approach is useful, but should it be the default?
I guess you can always change your message type to ‘a -> a’ and interpret with ‘id’ if you want to.
In Elm, the Model can be updated faster than the DOM. In other words, the view is rendered at the speed of requestAnimationFrame but the model can change in between animation frames. This means that if you handle model changes inside the view you might get out of sync with the model.
Here is a program [1] that shows this problem. If you click "SnapShot" you will sometimes get the same number but sometimes get different numbers.
Writing a lot of react (without redux) I never really miss serializeability and it’s easy to bolt on locally if you need it.
Besides already mentioned ability to serialize messages it also allows to preprocess or filter messages in the parent.
It was everywhere on conferences like 5 years ago.