Comments (11)
We used to have effects in the signal functions which made this easier, but removed them because it's easier to reason about the view if there are no effects involved. I guess this is the price for a pure signal function. I'll have a think about how we might resolve it.
from purescript-halogen.
@jdegoes I can see certain benefits of keeping the view pure, but this is an interesting point. Do you think it is worth thinking about moving Aff
back under the signal function?
from purescript-halogen.
@jdegoes Another option here is to stick a monad argument inside SF
, then we can keep pure signal functions where they're wanted, using Identity
, or use Aff
when we need requests. We could use type classes like MonadEff
for composition (or MonadCont
+ MonadEff
, etc.)?
from purescript-halogen.
Will post some thoughts here later today, have a meeting right now.
from purescript-halogen.
Here are some preliminary thoughts on this:
Currently, i
represents user events which are handled internally, user events intended to bubble up, external events (such as ticking of a clock), and possibly responses to requests. I'd suggest this is perhaps too overloaded and composition might improve if we are able to separate out distinct use cases.
This is just one idea, not very well thought out, but what are there portions of i
that could be hidden via existentials to simplify external composition? i.e. internal events intended to only affect the state?
Regardless, currently the type of View
is:
type View i p r = SF1 i (HTML p (Either i r))
This is very specific, the obvious generalization is:
type View i p r = SF1 i (HTML p r)
I think this introduces other complications since then you need a way to determine whether or not to feed back an event into the signal function or to pass it up to a handler. But still, worth thinking about as the more general signature could change composition (for better or worse).
Another approach would be to go more specific and incorporate requests q
and responses s
into the signature:
type View i p s q = SF1 (Either i s) (HTML p (Either i q))
The signal function is thus forced to process either a response to a request or a user input, and can emit either a user input, or a request.
If one hides i
via existentials and forces notifications along the request channel, one achieves the simpler:
type View p s q = ...
For some ugly looking existential type. Because you don't need to feed back i
's, the invariance is gone, and you have more compositional properties. Two views combine similarly to now: View (Either p p') (Either s s') (Either q q'))
or simpler variations as required.
type UI p s q eff =
{ view :: View p s q
, handler :: Handler q s eff
, renderer :: Renderer p
}
UI (Either p p') (Either s s') (Either q q')
. This again becomes invariant in both q
and s
because of handler / view. But prior to being wrapped in a UI
, pure views compose well. Also if you delete the handler, on the assumption that an app will only have one handler, possibly composed from different functions, then it's no longer invariant and composes better.
One could also consider prisms again. A prism can get you from a term to the sum, and can get you from a sum to maybe a term. It'd be nice if a component / UI / view (whatever we're composing) could be polymorphic in the type of the sum, and require (maybe via a type class constraint) that a prism exists between the sum type and whatever concrete term it requires. This would simplify composition in many ways: for example, an Ajax request type could service lots of views / components without having to redundantly Either
up the same type multiple times (although an Iso
could be used to simplify that).
I'll look at some of the work @natefaubion and get back if I have any more thoughts.
I'd sure hate to insert effects into signal functions just because it's the "easy" answer, especially if there's something better close at hand.
from purescript-halogen.
@jdegoes Another thought. What do you think about fusing the handler and view:
type View p m a b = SF1 a (HTML p (m b))
? I'm liking that idea more and more because it seems to make composition simple, and you keep the ability to mock requests for testing by using the Identity
monad or a free monad or something similar. You could even have mapView :: (m i -> n i) -> View p m i -> View p n i
to interpret the effect monad. m
basically takes the place of Either i r
.
runUI
would take a View p (Aff eff) i i
.
This seems like a nice way to bundle up reusable components, since View
is also a Profunctor
etc.
There is still the question of what to do with the renderer function which is still separate sadly.
from purescript-halogen.
Here is another reason to move Aff
inside HTML
: it should make the final encoding faster. If I can figure out how to avoid the newtype packing, there is still the issue of having to pass the driver function and renderer function on every call to element
, but this way, that wouldn't be needed since they'd be baked into the placeholder
and attr
calls.
from purescript-halogen.
I like type View p m a b = SF1 a (HTML p (m b))
, although it does suggest Placeholder
needs rethinking. Also at this point SF1
should probably be * -> * -> *
so you can define monad-aware instances for them. Maybe the Placeholder
constructor should bundle in everything it needs to render as a widget, or some such.
from purescript-halogen.
I think we can review and maybe close this in light of merging #50.
from purescript-halogen.
Ditto, any more comments @natefaubion before we close this one out in favor of other issues?
from purescript-halogen.
Yeah, I think we can close this.
from purescript-halogen.
Related Issues (20)
- `tellAll` function is not re-exported in Halogen module
- Enabling `StateT` with `HalogenM` HOT 1
- Export tellAll from Halogen.Query to Halogen HOT 2
- Reading Effects chapter -> Could not match type ResponseFormat String with type AffjaxDriver HOT 4
- Question: how to handle events coming from a js app? HOT 2
- Communication with JS loaded via CDN HOT 2
- Child component gets rendered outside of parent, being moved to bottom of HTML body HOT 6
- `raise` should not be a blocking operation HOT 8
- Discussion: CSS strategy for halogen applications HOT 20
- Question: body-level events HOT 3
- Order of properties matters when using `value` with `min` / `max` for `InputRange` HOT 3
- Change kind of slots to not be `Type`
- `RenderSpec` doc comment still mentions `h` parameter
- Doc: the examples of "An Aff Example: HTTP Requests" give TypesDoNotUnify Error on Halogen v7 HOT 1
- Select Multiple Selected does not work HOT 4
- A bug? Weird behavior of text input fields. HOT 4
- Child component is destroyed while parent component handles output from that child HOT 5
- Array state updates HOT 4
- open and showModal are missing for dialog HOT 6
- The Component type should have role annotations
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from purescript-halogen.