OvermindDL1 / bucklescript-tea

TEA for Bucklescript
Other
601 stars 45 forks source link

is it possible to integrate tea with redux #53

Closed tcoopman closed 7 years ago

tcoopman commented 7 years ago

Concrete question, I have a redux app and parts of it I want to port to bucklescript. This is not that hard, for example I can just switch the reducer with an update function. The problem is when I have an update function that next to the model also returns msgs and I want to execute them.

I was fiddling around a bit with Tea_cmd.js to call them or run them, but honestly I'm a bit lost and maybe I need to take a step back, but I thought it is worth a shot...

So I'm not sure that it's a good idea what I'm doing, and maybe I need a different approach, but if you have any pointers if it's possible to integreate the tea loop with reducers that would help :)

OvermindDL1 commented 7 years ago

There are certainly a few ways to do it (some may involve black magic), to give a better design I'd need to know more about what you are doing. Can you show some pseudo-code or a minimal example that I can look at to see what parts I need to fill in to get it working? :-)

Honestly though, in most things I'd probably have the tea app be self-contained and pass information into/out of it via standard DOM messages. They are fully encapsulated then and it would work with any api or libraries (I should probably make a 'fire event' command as a Cmd sometime to make that part dead simple, hmm...).

tcoopman commented 7 years ago

I transformed my problem a bit to work around it. Now I'm going to pass the redux dispatcher to my bucklescript code and let the bucklescript code pass redux actions out. In pseudo code it would be something like this:

const dispatcher // redux dispatcher
const actionCreator = require('./FromBucklescript).actionCreator
const buckleScriptReducer = require('./FromBucklescript).buckleScriptReducer

actionCreator(dispatcher, state);

const reducer = (state, action) => buckleScriptReducer(state, action);

And the buckleScriptReducer will transform actions to variant types internally and the actionCreator will transform variant types to redux actions.

In this way I don't use tea at all, but it solves my problem.

I am intrigued by the way of having a self-contained tea app though. What do you mean exactly by passing information via DOM messages?

(closing this as my initial problem was not really relevant to tea)

OvermindDL1 commented 7 years ago

(closing this as my initial problem was not really relevant to tea)

All good, I'm for discussing on closed issues. :-) I tend to only leave them open if they are something that I need to actively look at when I have code up. ^.^

I am intrigued by the way of having a self-contained tea app though. What do you mean exactly by passing information via DOM messages?

Basically I want to follow the webcomponent's HTML5 standard, and to accomplish that I want a TEA app to be able to also become a Custom Component in that spec, thus outside things pass information 'to' it either by setting attributes or properties depending (in TEA you'll be able to listen for those updates via Subscriptions) or by firing an event on the component (will also be a subscription). To pass information 'down' then the TEA app should either set attributes and/or properties (the lower then needs to poll it, so generally only useful for such styles) or more traditionally to fire a bubbling or not event on itself (event-depending) that the parent elements can listen to.

In other words, image taking, say, the Counter example app, register it under the counter-example name, then you could put it anywhere and anywhere in the DOM just by listing it's element there like:

...
<body>
  ... other stuff
  <counter-example value="42"></counter-example>
  ... even more stuff, let's put another though:
  <counter-example value="16"></counter-example>
  ... whatever depth too
</body>
...

This is all part of the HTML5 spec. :-)

Thus in something like Vuejs or Polymer (and react is similar but I don't have the syntax immediately in my mind) you could embed it into any app and even listen for updates for when, say, value changes by doing things like:

... Polymer boilerplate, here is the template section:
<div>
  <counter-example value="{{counterValue}}"></counter-example>
</div>

.. VueJS boilerplate, here is the template section, syntax might not be exactly right, but close enough:
<div>
  <counter-example value="{counterValue}" onvaluechanged="updateCounterValue"></counter-example>
</div>
.. And define the updateCounterValue callback, polymer does not need this as the functionality is built in:
updateCounterValue: function(evt) {
  this.value = evt.data.value;
}

Both polymer/vuejs/react/normalHTML/whatever could use it then just like it is any other normal HTML5 component. Like think of the textbox, it has attributes you can set like the line count displayed, it has properties like it's defaultValue and the current value you can set, you can read back things like the value to set what it currently contains, and you can listen to events on it for things like key presses and so forth, all of that is doable via the normal HTML5 webcomponents spec (and the polyfill for it all other than the Shadow DOM part, which I don't need, is nice and fast and small for the older crappy browsers).

But yes, just by following the HTML5 webcomponent spec. If you want more details the only main part of it I'd be using (as tea wraps up the rest, although things like the shadow dom would be very very useful once it is more ubiquitous, it is cheap enough to emulate) is Custom Elements (though if you are curious about the entire spec, including the parts that I do not need, you can read up on it at MDN too.

tcoopman commented 7 years ago

Thank you for taking the time writing this out. This look like something that would be really awesome! It looks like it is time that I read about the Web Component spec. I haven't looked at it for a while.

Also, how far of do you think tea is from doing something like this?

OvermindDL1 commented 7 years ago

Also, how far of do you think tea is from doing something like this?

Not far at all, at basics it is just writing some helpers (you can do it as-is currently if you do not mind a little boilerplater). What I'd like to do is break free from the Elm style API as it would allow a more simple and logical interaction between the parts then.

tcoopman commented 7 years ago

On the one hand I love the fact that this package stays as close to the Elm API as possible (most of the time I can just check the Elm documentation and it's trivial to port applications).

But on the other hand, I have the feeling that some things are possible in Bucklescript that aren't possible in Elm that would warrant moving away from Elm API to create something even better. I guess if you'd document where and why you do something in an other way than in Elm I would be fine with!

OvermindDL1 commented 7 years ago

A lot of things are possible in bucklescript that are not possible in Elm, just the module system alone allows for programming models than Elm could not even dream of (when I was playing around in bucklescript I started by making an elm-like API that built on modules instead). I entirely intend to start making extra modules here (TeaEnhanced?) that break the Elm API pretty severely but will take major advantage of what OCaml has to offer. :-)

jackalcooper commented 7 years ago

I can see that it will be much easier to reason about the code if Tea app is implemented upon a functor. On Wed, Oct 4, 2017 at 10:07 PM OvermindDL1 notifications@github.com wrote:

A lot of things are possible in bucklescript that are not possible in Elm, just the module system alone allows for programming models than Elm could not even dream of (when I was playing around in bucklescript I started by making an elm-like API that built on modules instead). I entirely intend to start making extra modules here (TeaEnhanced?) that break the Elm API pretty severely but will take major advantage of what OCaml has to offer. :-)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/OvermindDL1/bucklescript-tea/issues/53#issuecomment-334166867, or mute the thread https://github.com/notifications/unsubscribe-auth/AE5U9XGBxjZTyVhKJiD7vOM2CungQI5Lks5so5ERgaJpZM4PrMDN .

OvermindDL1 commented 7 years ago

I can see that it will be much easier to reason about the code if Tea app is implemented upon a functor.

Eh, even that is not necessary (though doing that for the vdom part could be interesting, though that would add a function indirection, preventing inlining by the javascript jit, so probably would not), but just having the module follow a signature and just using it straight does save on some code.

jackalcooper commented 7 years ago

@OvermindDL1 Oh, I meant not just save code. With a functor that should be easier to expose more functions for customization. Say custom VDOM, custom css, custom state managment and custom log even. Besides, the current inexplicit high kinded VDOM really give me a hard time to reason about it. Really want a functor to unify them in a clear and elegant way.

jackalcooper commented 7 years ago

My idea is that in Elm the author want to fully control the dev experience so it is OK to just build the library with pure composition. In BuckleScript, we enjoy flexibility and being customizable. That's why I think we should expose more underground functions with a functor so final users can implement the most suitable function in the scenario they are in.

OvermindDL1 commented 7 years ago

Functors would also make it slower due to the function indirections (they are basically implemented as an object with dynamic methods, thus incurring a dynamic call in a very tightly bound loop), hence why I've been hesitant. ^.^;

Besides, the current inexplicit high kinded VDOM really give me a hard time to reason about it.

o.O? How so? Functors are the same kind of high-kindedism in this case...

My idea is that in Elm the author want to fully control the dev experience so it is OK to just build the library with pure composition. In BuckleScript, we enjoy flexibility and being customizable. That's why I think we should expose more underground functions with a functor so final users can implement the most suitable function in the scenario they are in.

I plan to in enhanced versions, but in the base-most bucklescript-tea I am to follow the Elm api as to the letter as is reasonable. ^.^

Quite literally you can copy/paste most Elm code and add a header and fix Elm's funky function definitions and it 'just works'. ^.^