pselm / signals

Purescript implementation of Elm 0.16's signals modules
Other
91 stars 2 forks source link

Elm 0.17 and 0.18 compatibility #9

Open rgrempel opened 8 years ago

rgrempel commented 8 years ago

I've been taking a look at what is currently known about Elm 0.17, and thought I'd jot down a few thoughts.

One theme in Elm 0.17 is that the Elm runtime has become more coherently defined, with things like Platform and Program. I was going to have to do some of that conceptual work anyway (since I was going to have to define some kind of monad transformer stack to play the role of a runtime), so I can now follow Elm 0.17's lead (as much as is feasible).

Elm 0.17 now has a Cmd type, which is distinct from the Task type. At first glance, it appears that Cmd roughly corresponds to Purescript's Eff (with some additional wrinkles around feeding messages back into your program architecture), while Task continues to roughly correspond to Purescript's Aff. However, that may turn out to be wrong on further analysis.

Elm 0.17 also now has a Sub type, which is a kind of "subscription" to events. This replaces the concept of a Signal, but appears (at first glance) to have a smaller surface area in terms of an API. That is, you're no longer expected to construct a "signal graph" out of basic tools that could combine things in a variety of ways. Instead, your "subscription" feeds straight into the "start-app" structure (now Html.App), which had previously been just one way of managing a signal graph.

Of course, I'll need to translate the "subscription" idea. However, it might be interesting to also retain the old-fashionedSignal concept from Elm 0.16, if there is a sensible way for that to live alongside the new world. Alternatively, it might be interesting to try to build up some of the features of the old signal API on the subscription type.

Elm 0.17 also now has the concept of a special kind of module, which is an "effects" module. This appears to be a kind of module that can provide "hooks" for the runtime to exploit, related to things like initialization and the subscription / command handling system. This appears to be a way of formalizing some of the "magic" which the runtime used to do when setting up the signal graph (now, for setting up subscriptions and commands, presumably). For translating to Purescript, I would guess (at first glance) that it would be a question of typeclasses and/or monad transformer stacks (i.e. a module might implement a typeclass that allows it to participate in a defined way in what a monad transformer stack does to start up the app structure). But that may turn out to be wrong, on further analysis.

doppioslash commented 8 years ago

I, for one, vote to keep 0.16 compatibility. I might migrate an app I have working on Elm 0.16 to Purescript, and probably I'm not the only one.

rgrempel commented 8 years ago

Your wish is my command!

safareli commented 8 years ago

There might be 0.16 compatible branch also, but why should not we move on to be 0.17 compatible?

doppioslash commented 8 years ago

@safareli Can't we have both?

0.17 is more restrictive in some ways, so I have an app which makes heavy use of signals which I'd have to tear down and rebuild to port it to 0.17. Considering whether it may be better to port it to Purescript instead, and I'd wager other people with signal-heavy 0.16 apps will end up going this way as well.

rgrempel commented 8 years ago

Yes, I'd be looking to support both 0.16 and 0.17 -- I don't foresee any fundamental problem with doing that.

safareli commented 8 years ago

👍 Yes my point is that there should also be 0.17, but 0.16 could also be maintained.

rgrempel commented 8 years ago

Just a quick update on what I'm working on these days.

So, that is a kind of high-level map. This will take a little while -- I mean, I'm bad at estimating, but it looks more like a couple of months than a couple of weeks.

rehno-lindeque commented 7 years ago

@rgrempel A thought that occurred to me was that it might be possible to simply import the Elm run-time directly as JavaScript? One would then only need a way to convert Purescript values to Elm values at the interface?

This a lot less elegant I know, but it does have the rather significant advantage that one would be able to track new releases of Elm more easily. This is all just speculation of course...

rgrempel commented 6 years ago

I'm finally spending some more time on this stuff again!

So far, I've mostly been working over in purescript-elm-compat, updating it for Elm 0.17 and 0.18. That appears to be going reasonably well ... Elm 0.17 is done, and Elm 0.18 is in progress.

Then, I'll need to work on all the Cmd, Subscription stuff etc., to actually implement the Elm architecture.

When I was last working on this stuff, I got a fair ways down a rabbit hole of how one tests things for equality -- Elm uses referential equality under the hood at a few significant points, and I was trying to avoid that, which took me over to Data.Typeable and some interesting experiments.

In any event, I shall try to be more pragmatic when I get there now, and just do what Elm does! One can always experiment with improvements later.

And this may mean just copying some of Elm's Javascript into the Purescript implementation via the FFI ... we'll see if that simplifies certain things.

rgrempel commented 6 years ago

I've updated the stuff in this repository to compile with Purescript 0.11.7 and the current versions of various libraries etc.

Next step is to integrate with the latest code in purescript-elm-compat, and then explore the implementation of the Elm architecture as expressed in Elm 0.17 and 0.18's Cmd, Sub etc.

rgrempel commented 6 years ago

I've now updated the code here to use the latest stuff in purescript-elm-compat. So, that completes the "bring the old work up to date" phase. Now, it's a question of actually implementing the Elm architecture as of Elm 0.17 (and 0.18) ... i.e. using update, Cmd, Sub, etc.

As far as back-compat goes, I'm not going to delete the previous Signal stuff ... there's no particular reason to. Once the new work is done, there might be interesting ways to re-work the implementation of the old stuff in terms of the new stuff ... we'll see. (In theory, one might also be able to implement the new stuff in terms of the old stuff, but I'd actually like to take a fresh angle on it first, and see how that ends up).

I'm also not typically removing things that Elm removes ... I just note in the docs which Elm version removed them. So, I'm maintaining more back-compat than Elm does. (Which makes sense, I think, given the goals of this particular project).

Now, in some cases, there are inevitable back-compat problems, like the flipping of parameters for andThen in Elm 0.18. For that, I have some ideas about how to maintain a variant of the module with the original behaviour. But, it may not be a huge deal ... for the moment, I'm just documenting the changes that are inevitably breaking.

rgrempel commented 6 years ago

So, the action is now over at https://github.com/rgrempel/purescript-elm-compat/pull/4 ... there is enough Cmd and Sub stuff in elm-lang/core itself that I should be able to work out some kind of implementation before going further afield.

Once that's done, the next step would probably be to work on the virtual DOM / HTML stuff and get that updated.

rgrempel commented 6 years ago

So, the Elm.Platform stuff is now implemented in purescript-elm, which means that effect managers, Cmd, Sub, init, update, subscriptions are all working. Here's a simple example of an Elm-ish program in Purescript:

https://github.com/rgrempel/purescript-elm-compat/blob/master/examples/Simple.purs

So, that's kind of neat!

I should update this repo to work with the latest code in purescript-elm-compat ... I think that shouldn't be too difficult, as the changes there to things used here shouldn't be difficult to manage.

So, what's left? I still need to deal with Elm's characteristic interfaces with Javascript ... i.e. flags and ports. I've got a pretty good idea how to do that, and it shouldn't be too dificult.

I also need to implement the virtual DOM, and integrate that with the Elm.Platform code. I've already got a partial implementation of Elm 0.16's virtual DOM here. A quick look at Elm 0.17's virtual DOM suggests that the code hasn't changed radically. However, my implementation wasn't complete in the first place ... notably, I hadn't implemented event handling yet, so that's a pretty big gap. So, I'll need to do that.

Elm's virtual DOM is actually a thin wrapper over a lot of Javascript, so one option I ought to consider is taking the same Javascript and making a thin Purescript wrapper over it. However, I have enough of a start on an actual Purescript implementation that I think I'd prefer to try to finish that.

Then, there are some interesting ideas I should consider about how one interacts with purescript-elm from the Purescript side. From a Purescript point of view, an Elm program is ultimately an event loop with a mailbox to which messages can be sent. So, I suppose that the function which "launches" and Elm program could return the app's mailbox, so that Purescript could spin up an event loop and send it messages. (Since Purescript knows all the types involved, so wouldn't necessarily need to use ports). And, there may be interesting things that can be done with composing effects managers once I clean up the way they are setup and their types are handled. Ultimately, that may loop back into something reminiscent of Elm 0.16's signals ... it would be very interesting to me if, at the end of the day, it were possible to implement the Signal API on top of some kind of composition of programs or effect managers. But that's just a vague intuition at this point -- there may or may not end up being anything in it.

rgrempel commented 6 years ago

Just to jot down another vague thought, while it occurs to me. There is a curious parallelism in Elm between a program and an effect manager. They both consist of an event loop which manages state and processes messages. Now, there are some notable differences, so perhaps the similarities don't end up amounting to much. However, it would be very interesting if one ended up to be a kind of truncated example of the other, or if they both could be an example of something else. Again, just a vague intuition that may or may not work out to anything.

rgrempel commented 6 years ago

I've been working away at completing the implementation of the Virtual DOM -- I've finally started a PR at #16.

rgrempel commented 6 years ago

I've done a substantial re-organization of these repos, so this issue is probably more relevant on https://github.com/pselm/core now than it is here. I'll close it for now.

rgrempel commented 6 years ago

Actually, I'm not sure what I was thinking -- this issue is still relevant here -- I'll re-open for when I revisit this code.

devinrhode2 commented 6 years ago

On your core repo, might be nice to note in the top description the version of the Elm core library that's been implemented. Also is your signals repo really a work in progress, or would it make more sense to just deprecate it or at least mention it's "sort of deprecated"

Not to put words in your mouth, but it could be be nice to give users some clear direction, re-wording the readme as such:

This was a work-in-progress Purescript implementation of Elm 0.16's signal-related modules. It has now been Deprecated in favor of pselm/core which allows you to easily port your Elm 0.17 and 0.18 core to purescript. That is also where I have moved some descriptive text about differences between Elm and Purescript, and the status of the project as a whole.

(I hope I'm not misunderstanding the fact that signals and core have distinct, separate roles, but I could be).

rgrempel commented 6 years ago

Ah, yes, I am going to have to start communicating more clearly what parts of this are actually ready for use, now that some of it is!

Now that the core, html and http libraries are all partly working (there are some gaps), it's possible to start translating some more interesting Elm programs -- one of my next steps is to setup a little web-site illustrating that process.

The signals library isn't exactly deprecated -- it actually now has core as a dependency -- that is, it works on top of core, and still passes the tests it used to pass. But it is unfinished. One of the things on my to-do list is to return to it at some point and think more about how it relates to the Elm 0.17-0.18 architecture. Ideally, I'd like to build on the Elm 0.17-0.18 architecture by thinking about what it would mean to compose multiple "programs" together, and my intuition is that this might look a little bit like signals did. But we'll see!