Coder Social home page Coder Social logo

Comments (11)

paf31 avatar paf31 commented on July 22, 2024

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.

paf31 avatar paf31 commented on July 22, 2024

@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.

paf31 avatar paf31 commented on July 22, 2024

@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.

jdegoes avatar jdegoes commented on July 22, 2024

Will post some thoughts here later today, have a meeting right now.

from purescript-halogen.

jdegoes avatar jdegoes commented on July 22, 2024

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.

paf31 avatar paf31 commented on July 22, 2024

@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.

paf31 avatar paf31 commented on July 22, 2024

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.

jdegoes avatar jdegoes commented on July 22, 2024

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.

paf31 avatar paf31 commented on July 22, 2024

I think we can review and maybe close this in light of merging #50.

from purescript-halogen.

jdegoes avatar jdegoes commented on July 22, 2024

Ditto, any more comments @natefaubion before we close this one out in favor of other issues?

from purescript-halogen.

natefaubion avatar natefaubion commented on July 22, 2024

Yeah, I think we can close this.

from purescript-halogen.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.