-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Platform, Process, Cmd and Sub from Elm 0.18 #4
Conversation
So that we don't need the extra type variable for effects, which Elm's `Task` doesn't have. And, since Purescript is likely moving away from tracking the effect rows in any event.
Well, this is going nicely. I've now got the "surface" API of the effects managers roughed in, so that you can translate and type-check the "visible" Elm code in effects modules. All that's left is the hard part, actually making it do something. I'm debating whether to try to "mimic" what Elm actually does in its run-time, on the one hand, or simply implement what the types would require, on the other. I'll probably end up doing a bit of both. In any event, I'll be caught up in other things for a while now, so I'm not sure how soon I'll get back to this. Along the way, I switched the |
I've taken a quick look at what's in Elm's One thing that is neat in |
Well, all that's left is
Everything else is in place ... it's quite neat, actually, how far you can get by just following the types. |
So, what I'm working on now is essentially the Parts of it are straightforward enough, but it becomes apparent that So, thinking out loud a bit here, you create a function rawSpawn(task)
{
var process = {
ctor: '_Process',
id: _elm_lang$core$Native_Utils.guid(),
root: task,
stack: null,
mailbox: []
};
enqueue(process);
return process;
} I'm not paying too much attention to the What's interesting is the So, how does one make use of this mailbox? Here's the function rawSend(process, msg)
{
process.mailbox.push(msg);
enqueue(process);
}
function send(process, msg)
{
return nativeBinding(function(callback) {
rawSend(process, msg);
callback(succeed(_elm_lang$core$Native_Utils.Tuple0));
});
} So, this would have an Elm function signature roughly like: send :: Process msg -> msg -> Task x () Now, of course the Elm process is not parameterized, but this kind of process would ideally need to be. Come to think of it, the "future directions" comment in Plstform.elm suggests as much -- it speculates that the future API for a type Id exit msg
spawn : Task exit a -> Task x (Id exit Never)
kill : Id exit msg -> Task x ()
send : Id exit msg -> msg -> Task x () But, in fact, it seems that it already is this way under the hood, at least to a degree. Just as an aside, this ability to send messages between processes is just a bit reminiscent of Elm 0.16's signals ... in a sense, this might be where the idea of signals pokes up its head in Elm 0.17. Also, it has an interesting relationship to effects managers, which I'l need to explore. So, Then, there appears to be a task which would "receive" a message on the processes's mailbox, if there is a message: if (ctor === '_Task_receive')
{
var mailbox = process.mailbox;
if (mailbox.length === 0)
{
break;
}
process.root = process.root.callback(mailbox.shift());
++numSteps;
continue;
} So, how do you get one of those tasks? There is a function receive(callback)
{
return {
ctor: '_Task_receive',
callback: callback
};
} Now, what's the Elmish signature of the receive : msg -> Task ? ? So, it doesn't do any good to I doubt that Aff's Fiber has anything quite like this, though I'll look. In Purescript terms, this might have something to do with continuations, or with streams -- ideally, it will be another monad transformer that I can layer on top of The other alternative would be to make this kind of |
Ah, Aff's concept of an |
I've been working away at implementing a kind of
Working away at this for a bit, it was reasonably clear that it could be made to work. However, it meant that And that would be doable, of course, but I'm trying to avoid adding type parameters where Elm doesn't have them. That is, I'd rather not have Thinking that over, it occurred to me that, at least for now, this plan was actually more ambitious than it needed to be. The plan would have allowed constructing tasks and processes that at arbitrary moments waited for a message to be sent to the mailbox, and then went along and did other things. That's probably something that Elm will have eventually, but it's not what it has now -- the only thing which actually sends or receives messages now is the kernel itself. And, it does so in what is essentially just a very tight loop -- it just waits for a message, then dispatches it in a characteristic way. So, I don't really need (yet) to integrate the sending and receiving of messages between processes into the ordinary flow of tasks. Instead, it can be a "special" thing, to implement the specific things that the kernel does. Now, of course, the Elm kernel uses tasks to implement all of this, but that's mostly because what it's got is tasks. In my case, I don't necessarily have to bring this into So, now I'm imagining a set of distinct types to implement the stuff that Elm is doing "under the covers" here. Ultimately, it remains true that the message passing will involve |
So, I've reverted the commits that added a mailbox to every process, and I'll start again with a separate type for receiving & dispatching messages. |
Yes, Plan B is much better ... the main event loop and the event loops for the effects managers are now mostly done. It ended up being easier not to implement the Elm Javascript too literally -- it was, once again, better to follow the types, as usual. |
Eureka! |
This should be fun!
Once finished, this will enable "headless" Elm programs, and will essentially completely implement the
elm-lang/core
from Elm 0.18. The next step would then be to implementelm-lang/html
.