bodil / purescript-signal

Elm style FRP library for PureScript
Apache License 2.0
258 stars 44 forks source link

Question: break out JS lib? #18

Closed paf31 closed 9 years ago

paf31 commented 9 years ago

I have a proposal for this library.

I've been working on https://github.com/paf31/purescript-behaviors, mostly to learn FRP concepts, and I think it fits a different niche to this library - signals seems better suited to things like reactive UIs and games, and behaviors seems better for things like modeling continuous functions and simulations. The key difference seems to be whether signals have to be defined at time zero or not.

Anyway, my main lesson from working on behaviors was that it was a good thing to break out the JavaScript from the FFI imports into an actual library. I think it would be good to see more libraries developed in this way - a JS library inspired by functional concepts, with a thin PureScript wrapper to provide types and standard type class instances.

I also think this would be a great way to get more JS developers on board.

What do you think? Would you accept a PR along these lines?

I also think this would be good in the sense that it would force us to think about the denotation of Signal. Right now, there is quite a lot of usage of the constant function to create signals, and I find it difficult to understand the interface.

alvinwng commented 9 years ago

Wouldn't it be nice to generalize this library to allow for signals without an initial value? Then Signal can be made into a monoid with mempty to be such signal and merge as its binary operation. Perhaps its behavior would then be closer to your behaviors library? I am thinking about implementing this signal without an initial value such that the initial value is null in JS, but not sure if this would be alright in the sense of PureScript.

paf31 commented 9 years ago

I vote :-1: on this.

Signals being defined everywhere is a design choice (matching Elm). This is why I made the distinction between behaviors (defined everywhere) and events (discrete, initially empty) in purescript-behaviors, but it's a different set of design choices with different goals.

I think that for things like signals of DOM elements, the choices made by this library are the most appropriate.

For things like continuous functions and simulations, I think that the approach taken by purescript-behaviors is more appropriate.

alvinwng commented 9 years ago

I think signals being defined all the time is, as you said, a design choice to match Elm, and that's the only reason I can see. In the usual sense of the word "signal", a signal may or may not occur at all. If it has to be there all the time, I think it's better called a status. This library is also used to model keyboard inputs and timers, as seen in Signal.DOM and Signal.Time. But the requirement that a signal has to be there all the time makes the modelling of keypress much like key status, and the modelling of timeout in JS pretty much impossible, as a signal is fired right away at the time of subscription. I would need extra code to check if it's being fired for the first time, which is cumbersome. I do not see much sense in this Elm design and think that allowing signals that may or may not occur at all would give more flexibility to this library.

paf31 commented 9 years ago

I do agree that things like mouse and keyboard Signals are a bit odd. That was part of the inspiration for my behaviors library, but I also don't think that my solution is appropriate for modeling an updatable DOM. You don't want to have to sample a behavior every N milliseconds just to update the DOM, which is the only option right now - you want a push model in this case. But I do think there is a middle ground, by defining types for both signals and non-empty signals. Whether that is something that @bodil wants to explore with this library is not really for me to say, though.

bodil commented 9 years ago

The only aim of this library is to implement signals in the Elm style. Anything else is out of scope and best done as a separate project. I heard Behaviours is pretty cool. :)

And as to the original point: with inline FFI, I get dead code elimination and no ambiguity about how to load the JS. One of the design goals of this implementation was to be tiny, so the DCE is something I'm very reluctant to give up.

We should also explore the implications of bundling JS files in packages before making this a thing - it makes things potentially tricky for build systems and runtimes. Not saying it's a bad idea in the long term, though, I can see how it could be useful.

paf31 commented 9 years ago

Makes sense, thanks.