* Recursion on React.events.
@ 2009-12-09 2:40 Guillaume Yziquel
2009-12-09 3:22 ` Guillaume Yziquel
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Guillaume Yziquel @ 2009-12-09 2:40 UTC (permalink / raw)
To: OCaml List, Daniel Bünzli
Hello.
I've been dabbling with recursive definition of React events.
Suppose I have a function called schedule of type
val schedule : Calendar.t -> unit React.event
which throws out an event at the specified time or date.
I've been trying to create a regular_schedule function that throws
events at a regular pace. Daniel Bünzli's module is great, but sometimes
a bit rough to get by, specifically on examples such as this one.
So I came up with a recursive definition of such a React.event:
> let rec regular_schedule start_time period =
> React.E.switch React.E.never begin React.E.map
> begin fun () -> regular_schedule (Calendar.add (Calendar.now ()) period) period end
> begin schedule start_time end
> end
First question:
It almost works, in the sense that if you insert a print_endline after
the fun (), well, it indeeds prints stuff on stdin at the specified
pace. However, somehow, the event as a whole behaves as React.E.never.
So it doesn't work. I guess it has to do with the way React.switch works
synchronously, but I really do not get it.
Second question:
Is there somehow a notion of 'tail recursion' for such constructs?
All the best,
--
Guillaume Yziquel
http://yziquel.homelinux.org/
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 2:40 Recursion on React.events Guillaume Yziquel @ 2009-12-09 3:22 ` Guillaume Yziquel 2009-12-09 4:25 ` Daniel Bünzli 2009-12-09 7:53 ` Daniel Bünzli 2 siblings, 0 replies; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-09 3:22 UTC (permalink / raw) To: OCaml List, Daniel Bünzli Guillaume Yziquel a écrit : > Hello. > > I've been dabbling with recursive definition of React events. > > Suppose I have a function called schedule of type > > val schedule : Calendar.t -> unit React.event > > which throws out an event at the specified time or date. > > I've been trying to create a regular_schedule function that throws > events at a regular pace. Daniel Bünzli's module is great, but sometimes > a bit rough to get by, specifically on examples such as this one. > > So I came up with a recursive definition of such a React.event: > >> let rec regular_schedule start_time period = >> React.E.switch React.E.never begin React.E.map >> begin fun () -> regular_schedule (Calendar.add (Calendar.now ()) >> period) period end >> begin schedule start_time end >> end > > First question: > > It almost works, in the sense that if you insert a print_endline after > the fun (), well, it indeeds prints stuff on stdin at the specified > pace. However, somehow, the event as a whole behaves as React.E.never. > So it doesn't work. I guess it has to do with the way React.switch works > synchronously, but I really do not get it. OK. The following piece of code works out, but it seems to me that using a React.E.select in this position is a rather ugly hack. let rec regular_schedule start period = let waiting_for = schedule start in React.E.switch React.E.never begin React.E.map begin fun () -> React.E.select [waiting_for; regular_schedule (Calendar.add (Calendar.now ()) period) period] end waiting_for end > Second question: > > Is there somehow a notion of 'tail recursion' for such constructs? I gave some thought to it, and it seems quite plausible that what is done in the first place is analoguous to tail recursion. And that using React.E.select breaks the tail recursion. Am I offtrack? > All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 2:40 Recursion on React.events Guillaume Yziquel 2009-12-09 3:22 ` Guillaume Yziquel @ 2009-12-09 4:25 ` Daniel Bünzli 2009-12-09 18:47 ` Guillaume Yziquel 2009-12-09 7:53 ` Daniel Bünzli 2 siblings, 1 reply; 15+ messages in thread From: Daniel Bünzli @ 2009-12-09 4:25 UTC (permalink / raw) To: guillaume.yziquel; +Cc: caml-list >> let rec regular_schedule start_time period = >> React.E.switch React.E.never begin React.E.map >> begin fun () -> regular_schedule (Calendar.add (Calendar.now ()) >> period) period end >> begin schedule start_time end >> end Look at the semantic definition of E.switch in the documentation. When a tick happens the whole switch switches instantaneously to the event for the new tick returned by regular_schedule which will happen in now+period. You never see ticks because as soon a tick happen you replace the event that should "show" the tick by "showing" the next tick. Anyway don't do any recursive tricks unless you really know what you are doing (which you don't seem). You are asking for trouble (infinite loops and puzzling behaviour more precisely). The ONLY right way to define recursive events and signals is to use the fixed point operators. So in your case something like this should work : let regular_schedule start_time period = let define tick = (* tick is the value of tick' dt times ago *) let tick' = let reschedule () = Calendar.add (Calendar.now ()) period in React.E.switch (schedule start_time) (E.map reschedule tick) in tick', tick' in E.fix define So basically after a tick' happens, tick will immediatly (but not instantaneously) happen and reschedule a new tick' occurence. Note that in general I would avoid what you are doing altoghether by providing regular_schedule as a primitive as you do for schedule. If you are using too much ugly side effects and tricks in your event definitions then you loose all the benefits of frp. Best, Daniel P.S. You may want to have a look at rtime : http://erratique.ch/software/rtime ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 4:25 ` Daniel Bünzli @ 2009-12-09 18:47 ` Guillaume Yziquel 2009-12-10 8:39 ` Daniel Bünzli 0 siblings, 1 reply; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-09 18:47 UTC (permalink / raw) To: Daniel Bünzli; +Cc: caml-list Daniel Bünzli a écrit : >>> let rec regular_schedule start_time period = >>> React.E.switch React.E.never begin React.E.map >>> begin fun () -> regular_schedule (Calendar.add (Calendar.now ()) >>> period) period end >>> begin schedule start_time end >>> end > > Anyway don't do any recursive tricks unless you really know what you > are doing (which you don't seem). You are asking for trouble (infinite > loops and puzzling behaviour more precisely). The ONLY right way to > define recursive events and signals is to use the fixed point > operators. So in your case something like this should work : > > let regular_schedule start_time period = > let define tick = (* tick is the value of tick' dt times ago *) > let tick' = > let reschedule () = Calendar.add (Calendar.now ()) period in > React.E.switch (schedule start_time) (E.map reschedule tick) > in > tick', tick' > in > E.fix define Thanks. This works perfectly! (I mean, with the tweak you mentioned in your second email). I still do not understand why there's the couple (tick', tick') and not simply tick', nevertheless... > Note that in general I would avoid what you are doing altoghether by > providing regular_schedule as a primitive as you do for schedule. If > you are using too much ugly side effects and tricks in your event > definitions then you loose all the benefits of frp. Well, I do not fully agree. While I agree that keeping code clear and non-confusing is the best option, I do not really know if I can avoiding doing such magic. My use case is the following: I'm writing a scheduler that I hope to extend smartly over time. It's a scheduler that is based on Calendar, and that runs in a Lwt.thread. Source code is given below, at the end of this email. There's a schedule function that somehow registers a task in the scheduler, and returns a React.E.event on which code using the library can hook to. Making a regular_schedule in the way you suggested proved to be quite difficult without changing the code of the scheduler itself, which I'd like to keep clean and small. Moreover, I also aim to make a auto_schedule function that does some rescheduling at with a delay that is know at the time of rescheduling. Generally speaking, I want to keep the scheduler small and clean, and give flexibility to the user of the scheduling library. So providing regular_schedule as a primitive does not seem to me to fit this perspective. > Best, > > Daniel > > P.S. You may want to have a look at rtime : http://erratique.ch/software/rtime Cool. One criticism and one question. Criticism: it doesn't use Calendar, which really a cool library. Question: How well does Rtime interact with Lwt? I'll have a look at what I can do with it. Here's the code of the scheduler: > open Lwt > open CalendarLib > > type task = { > schedule : Calendar.t; > trigger : unit -> unit; } > > let compare t1 t2 = > let n = Calendar.Date.compare > (Calendar.to_date t1.schedule) > (Calendar.to_date t2.schedule) in > if n = 0 then CalendarLib.Calendar.Time.compare > (Calendar.to_time t1.schedule) > (Calendar.to_time t2.schedule) > else n > > let tasks : task list ref = ref [] > > let register_new_task t = > let rec aux = function | [] -> t::[] | hd::tl -> > begin match compare hd t with > | 1 -> t::hd::tl | _ -> hd::(aux tl) end > in tasks := aux !tasks > > let (read_control_fd, write_control_fd) = Lwt_unix.pipe () > > let task_channel = ref None > let task_mutex = Lwt_mutex.create () > > let _ = > let rec receive_order = let buffer_command = " " in begin fun () -> > match Unix.read (Lwt_unix.unix_file_descr read_control_fd) buffer_command 0 1 with > | 1 -> begin match !task_channel with > | Some new_task -> begin > task_channel := None; > Lwt_mutex.unlock task_mutex; > register_new_task new_task; > loop () end > | None -> assert false > end > | _ -> assert false end > and loop () : unit Lwt.t = match !tasks with > | [] -> Lwt_unix.wait_read read_control_fd >>= fun () -> receive_order () > | hd::tl -> let float_delay = > Calendar.Time.Second.to_float ( > Calendar.Time.Period.to_seconds ( > Calendar.Period.to_time ( > Calendar.sub hd.schedule ( > Calendar.now ())))) in > begin match float_delay > 0. with > | false -> tasks := tl; hd.trigger (); loop () > | true -> Lwt.catch begin fun () -> > Lwt_unix.with_timeout float_delay begin function () -> > Lwt_unix.wait_read read_control_fd >>= fun () -> > receive_order () end > end begin function > | Lwt_unix.Timeout -> tasks := tl; hd.trigger (); loop () > | _ -> assert false > end end in > loop () > > let schedule date = > let aux () = > let (e, set_e) = React.E.create () in > Lwt_mutex.lock task_mutex >>= fun () -> > task_channel := Some {schedule = date; trigger = set_e;}; > Lwt_unix.write write_control_fd "X" 0 1 >>= function > | 1 -> Lwt.return e | _ -> assert false in > Lwt_main.run (aux ()) > > let regular_schedule start period = > (* The let define tick in E.fix define is the proper way to > implement recursive events. define has type React.event -> > (React.event * React.event) and its argument is a placeholder > for the event at time t-dt. *) > let define tick = > let tick' = React.E.switch (schedule start) (React.E.map begin function () -> > schedule (Calendar.add (Calendar.now ()) period) end tick) in > tick', tick' > in > React.E.fix define -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 18:47 ` Guillaume Yziquel @ 2009-12-10 8:39 ` Daniel Bünzli 0 siblings, 0 replies; 15+ messages in thread From: Daniel Bünzli @ 2009-12-10 8:39 UTC (permalink / raw) To: guillaume.yziquel; +Cc: caml-list > I still do not understand why there's the couple (tick', tick') and not > simply tick', nevertheless... The tick' on the left is the event you are delaying (i.e. the one you will receive as an argument to defining function but delayed). The tick' on the right is what you want to get out from the defining function, here both are equal but that may not be always the case. > >> Note that in general I would avoid what you are doing altoghether by >> providing regular_schedule as a primitive as you do for schedule. If >> you are using too much ugly side effects and tricks in your event >> definitions then you loose all the benefits of frp. > > Well, I do not fully agree. In fact I retract my comment in that case. I thought you were playing dirty tricks but in fact you were not. Sorry. > Cool. One criticism and one question. > > Criticism: it doesn't use Calendar, which really a cool library. I don't think you need Calendar to provide what rtime provides. > Question: How well does Rtime interact with Lwt? No idea I have never used Lwt. Daniel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 2:40 Recursion on React.events Guillaume Yziquel 2009-12-09 3:22 ` Guillaume Yziquel 2009-12-09 4:25 ` Daniel Bünzli @ 2009-12-09 7:53 ` Daniel Bünzli 2009-12-09 11:23 ` [Caml-list] " Richard Jones 2009-12-09 18:24 ` Guillaume Yziquel 2 siblings, 2 replies; 15+ messages in thread From: Daniel Bünzli @ 2009-12-09 7:53 UTC (permalink / raw) To: guillaume.yziquel; +Cc: OCaml List > Daniel Bünzli's module is great, but sometimes a bit rough > to get by, specifically on examples such as this one. I would just like to point out that this has nothing to do with the module per se but understanding frp in general and this is the reason why I went to great length to document the semantics for each of the combinators I provide --- something most frp libraries won't bother to do, leaving you with testing or looking into the implementation for understanding things when tricky simulateneity issues arise. Thus to understand why your event didn't work you could have done the following. Provided you understand the notations given here : http://erratique.ch/software/react/doc/React#sem 1) Define a semantics for your primitive events and functions. [Calendar.schedule st]_t = Some () iff t = st [Calendar.now ()]_t = t 2) Reason on your expression, by applying the semantics of the combinators and your primitives. Let's try to look what happens at st for (regular_schedule st p) assuming p > 0. [regular_schedule st p]_st = [E.switch E.never ee]_st with ee = E.map (fun () -> regular_schedule ...) (schedule st) Since we have [schedule st]_st = Some (), by the semantics of E.map we have [ee]_st = Some ev. Thus we are in the second case of the semantics of E.switch (see doc) and the semantics of the switch reduces to the semantics of ev, i.e. [E.switch E.never ee]_st = [regular_schedule (Calendar.add (Calendar.now ()) p) p]_st = [E.switch E.never ee']_st with ee' = E.map (fun () -> regular_schedule ..) (schedule (st + p)) Now by the semantics of schedule and E.map you know nothing will happen on ee' before st + p ans since p > 0 we are in the first case of the semantics of E.switch and the last switch reduces to the semantics of E.never. To sum up : [regular_schedule st p]_st = [E.never]_st = None So at st, nothing happens, as you witnessed. Applying the same technique you could generalize the result for any t. Pure equational reasoning, it's not that hard, or is it ? Best, Daniel P.S. In my previous email let reschedule () = Calendar.add (Calendar.now ()) period should read let reschedule () = schedule (Calendar.add (Calendar.now ()) period) I misunderstood the type of Calendar.add. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Caml-list] Re: Recursion on React.events. 2009-12-09 7:53 ` Daniel Bünzli @ 2009-12-09 11:23 ` Richard Jones 2009-12-09 18:01 ` Guillaume Yziquel 2009-12-09 18:24 ` Guillaume Yziquel 1 sibling, 1 reply; 15+ messages in thread From: Richard Jones @ 2009-12-09 11:23 UTC (permalink / raw) To: Daniel Bünzli; +Cc: guillaume.yziquel, OCaml List On Wed, Dec 09, 2009 at 03:53:36PM +0800, Daniel Bünzli wrote: > > Daniel Bünzli's module is great, but sometimes a bit rough > > to get by, specifically on examples such as this one. > > I would just like to point out that this has nothing to do with the > module per se but understanding frp in general [...] Personally I've yet to read any comprehensible introduction to FRP. I'm interested in whether FRP can be used to write Gtk interfaces with reduced code complexity. Apparently it can, but I've no idea how. Rich. -- Richard Jones Red Hat ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Caml-list] Re: Recursion on React.events. 2009-12-09 11:23 ` [Caml-list] " Richard Jones @ 2009-12-09 18:01 ` Guillaume Yziquel 2009-12-10 3:38 ` Daniel Bünzli 0 siblings, 1 reply; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-09 18:01 UTC (permalink / raw) To: Richard Jones; +Cc: Daniel Bünzli, OCaml List Richard Jones a écrit : > On Wed, Dec 09, 2009 at 03:53:36PM +0800, Daniel Bünzli wrote: >>> Daniel Bünzli's module is great, but sometimes a bit rough >>> to get by, specifically on examples such as this one. >> I would just like to point out that this has nothing to do with the >> module per se but understanding frp in general [...] > > Personally I've yet to read any comprehensible introduction to FRP. > I'm interested in whether FRP can be used to write Gtk interfaces with > reduced code complexity. Apparently it can, but I've no idea how. > > Rich. Concerning documentation, Daniel's documentation is pretty good, and it's all that's been necessary to get me going. You should try having a look at it. I have little experience with Gtk, but I've written an Eliom web application using the ExtJS framework for windowing in browsers. In some sense, it's more complex than a Gtk application, because you have to manage lots of users, sessions, et ceteræ. Moreover the Eliom module was keeping track of the state of an Asterisk server, and initiating phone calls. I must say that using React was the only way to write the application cleanly and in a minimum amount of time. I was basically using signals for: -1- proxying persistent information such as user data and configuration in the SQLite database -2- parsing the output of the text-based Asterisk Manager Interface -3- keeping track of the state of the Asterisk server, and interacting with it (making phone calls, when the phone hangs up, when a call could not be made, etc...) -4- Keeping track of the IP of users of the web application coming from Ocsigen, and reconciliation with the IP of the softphones as registered by Asterisk (this allowed to avoid using passwords on the LAN) -5- Keeping track of the history of the phone calls made by agent, and feed it back to the administrator's web session -6- Doing all the "real-time" AJAX interaction for updating tables, windowing, et ceteræ. Doing it in a FRP way allowed to focus on the semantics, and moreover React update cycles integrate nicely with Lwt as used by Ocsigen. So you can do really cool stuff with it. It took me roughly one and half to two weeks from scratch (including learning the ExtJS library, troubleshooting the Asterisk Manager Interface, et ceteræ), with quite a lot of other concurrent obligations to handle. So yes, FRP is really cool. Unfortunately, it seems to me that Daniel's module is fairly low-level in the sense that it implements the bare mechanics and semantics of FRP. For real world application, you have to be quite nifty with tricky details about update cycles. For example, make a parser of the Asterisk Manager Interface with React around OCamlNet's Uq_engine module proved to be quite tricky, in a similar way as the issue that started this thread (here, I had no event, but in the Asterisk parser, I had doubled events, and I solved it in a very very ugly way). It's true that I may not completely understand how React works, as Daniel stated it before (a bit better now), but, for instance, the React.E.switch or React.S.switch is something that you'll be using a lot. And I feel the need for higher-level functions to deal with it, even though I do not have yet a precise idea of which such functions. All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Caml-list] Re: Recursion on React.events. 2009-12-09 18:01 ` Guillaume Yziquel @ 2009-12-10 3:38 ` Daniel Bünzli 2009-12-10 22:24 ` Guillaume Yziquel 0 siblings, 1 reply; 15+ messages in thread From: Daniel Bünzli @ 2009-12-10 3:38 UTC (permalink / raw) To: guillaume.yziquel; +Cc: Richard Jones, OCaml List > Unfortunately, it seems to me that Daniel's module is fairly low-level in > the sense that it implements the bare mechanics and semantics of FRP. Yes, react is low-level and will remain. The rationale is that I want the client of the module to be able to decide the application structure. This makes react more flexible and easier to embed were you need to. I could have decided that react has a global queue and every primitive update has to go through that queue (for the client this would have simplified the feedback of primitives into the reactive system). But then the module is not thread-safe and you get compositional problems when you want to integrate two libraries using react in a threaded environment. I could have decided that the reactive engine runs on its own thread but maybe you don't want to use threads etc. For example with the current design two part of a program may use react as they wish internally without any problem even on different threads as long as their signals and events don't interact. With the current structure it also means that a library designer using react has to make sure the way he design should play nice with other part defining their own primitive events. So yes it means a little bit more work and understanding for the client. But I think it pays to have a reactive engine that doesn't impose too much on you. The client always knows better the abstraction he's after and the setting in which it has to implement it. But if a consistent and compositional pattern of use emerges I'm always willing to support it directly in the library. > For example, make a parser of the Asterisk Manager Interface > with React around OCamlNet's Uq_engine module proved to be quite tricky, in > a similar way as the issue that started this thread (here, I had no event, > but in the Asterisk parser, I had doubled events, and I solved it in a very > very ugly way). Note that as we discussed I highly suspect you used the wrong abstraction there (events vs. signals). > It's true that I may not completely understand how React works, as Daniel stated it before (a bit better now) Btw this was not intended to be offensive. It was to say the reactive engine has a well defined way to work that should be respected (the update cycle) so don't try to trick around too much with it when you cannot achieve want you want. Best, Daniel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Caml-list] Re: Recursion on React.events. 2009-12-10 3:38 ` Daniel Bünzli @ 2009-12-10 22:24 ` Guillaume Yziquel 2009-12-11 12:16 ` Jérémie Dimino 0 siblings, 1 reply; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-10 22:24 UTC (permalink / raw) To: Daniel Bünzli; +Cc: Richard Jones, OCaml List Daniel Bünzli a écrit : >> Unfortunately, it seems to me that Daniel's module is fairly low-level in >> the sense that it implements the bare mechanics and semantics of FRP. > > Yes, react is low-level and will remain. The rationale is that I want > the client of the module to be able to decide the application > structure. This makes react more flexible and easier to embed were you > need to. That's perfect. You should perhaps think of creating a Convenience submodule where some useful patterns could be thrown in by third parties. After having been 'moderated' by you, of course. > I could have decided that react has a global queue and every primitive > update has to go through that queue (for the client this would have > simplified the feedback of primitives into the reactive system). But > then the module is not thread-safe and you get compositional problems > when you want to integrate two libraries > using react in a threaded environment. I could have decided that the > reactive engine runs on its own thread but maybe you don't want to use > threads etc. No no no! Indeed, it's much better as it is today. > For example with the current design two part of a program may use > react as they wish internally without any problem even on different > threads as long as their signals and events don't interact. With the > current structure it also means that a library designer using react > has to make sure the way he design should play nice with other part > defining their own primitive events. Yes, indeed. But that's also the tricky part where some useful constructs would indeed be... useful. > So yes it means a little bit more work and understanding for the > client. But I think it pays to have a reactive engine that doesn't > impose too much on you. The client always knows better the abstraction > he's after and the setting in which it has to implement it. But if a > consistent and compositional pattern of use emerges I'm always willing > to support it directly in the library. All to true. But that would be the purpose of a Convenience submodule (once you get constructive feedback). >> For example, make a parser of the Asterisk Manager Interface >> with React around OCamlNet's Uq_engine module proved to be quite tricky, in >> a similar way as the issue that started this thread (here, I had no event, >> but in the Asterisk parser, I had doubled events, and I solved it in a very >> very ugly way). > > Note that as we discussed I highly suspect you used the wrong > abstraction there (events vs. signals). Very possibly. I will have to get back to it one day to make it clean. Now that I know where to find the documentation for E.fix, it's only a question of *cough* time *cough*. >> It's true that I may not completely understand how React works, as Daniel stated it before (a bit better now) > > Btw this was not intended to be offensive. It was to say the reactive > engine has a well defined way to work that should be respected (the > update cycle) so don't try to trick around too much with it when you > cannot achieve want you want. Yes. It's also here where I worry about a few things concerning Lwt: In Lwt, you have a monadic way to do context switches for multithreading withing a single real thread. So if you use Lwt inside the update cycle, you could well jump out of the update cycle with a Lwt context switch. As long as you do not encounter a Lwt construct within definition of signals and events, you can be pretty sure that the update cycle will go through to its end without using Lwt inside an event/signal. But at the same time, it seems that the monadic way Lwt is built avoids us such problems. But I may be mistaken. This issue can be interesting and important. 'a Lwt.t represents the type of a promise of something of type 'a, essentially. So you could use in parallel processing: Imagine that 'a Remote.t represents the type of something computed on a remote computer. You could use type 'a Remote.t Lwt.t to represent the promise of a computation of 'a done on a remote computer. It therefore could make sense to have a single computer in charge of receiving React.events with a unique update cycle, and transfering the computation to other computers, represented as non-primary 'a Remote.t Lwt.t React.signal-s. Using S.fix, one could also feed events to such a signal, using S.fix to bind the t-dt Lwt.t value of the signal to the t value of the same signal. That may seem quite involved, but conceptually, it could be a clean way to type rather efficiently parallel computations. When binding such signals, you could also implement code mobility, marshaling features to take care of the work load of multiple computers. So the compatibility of Lwt and React seems to me a worthwile question if one wants to use OCaml for high availability, reactive, parallel computations. And in this context, making E/S.switch easy to use would quite important... > Best, > > Daniel All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Caml-list] Re: Recursion on React.events. 2009-12-10 22:24 ` Guillaume Yziquel @ 2009-12-11 12:16 ` Jérémie Dimino 0 siblings, 0 replies; 15+ messages in thread From: Jérémie Dimino @ 2009-12-11 12:16 UTC (permalink / raw) To: guillaume.yziquel; +Cc: OCaml List Le jeudi 10 décembre 2009 à 23:24 +0100, Guillaume Yziquel a écrit : > Yes. It's also here where I worry about a few things concerning Lwt: > > In Lwt, you have a monadic way to do context switches for multithreading > withing a single real thread. So if you use Lwt inside the update cycle, > you could well jump out of the update cycle with a Lwt context switch. > As long as you do not encounter a Lwt construct within definition of > signals and events, you can be pretty sure that the update cycle will go > through to its end without using Lwt inside an event/signal. But at the > same time, it seems that the monadic way Lwt is built avoids us such > problems. But I may be mistaken. It is possible to use Lwt inside an update cycle. It is not a problem to switch context in an update cycle as long as you respect React's rules. > So the compatibility of Lwt and React seems to me a worthwile question > if one wants to use OCaml for high availability, reactive, parallel > computations. And in this context, making E/S.switch easy to use would > quite important... Thanks to React being lowlevel, the two libraries are compatible out of the box. Jérémie ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 7:53 ` Daniel Bünzli 2009-12-09 11:23 ` [Caml-list] " Richard Jones @ 2009-12-09 18:24 ` Guillaume Yziquel 2009-12-10 8:24 ` Daniel Bünzli 1 sibling, 1 reply; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-09 18:24 UTC (permalink / raw) To: Daniel Bünzli; +Cc: OCaml List Daniel Bünzli a écrit : >> Daniel Bünzli's module is great, but sometimes a bit rough >> to get by, specifically on examples such as this one. > > I would just like to point out that this has nothing to do with the > module per se but understanding frp in general and this is the reason > why I went to great length to document the semantics for each of the > combinators I provide --- something most frp libraries won't bother to > do, leaving you with testing or looking into the implementation for > understanding things when tricky simulateneity issues arise. I appreciate the documentation effort you put up. Really. > Thus to understand why your event didn't work you could have done the > following. Provided you understand the notations given here : > > http://erratique.ch/software/react/doc/React#sem I do. I've done quite a lot of maths after all, and this doesn't frighten me. > Since we have [schedule st]_st = Some (), by the semantics of E.map we > have [ee]_st = Some ev. Thus we are in the second case of the semantics > of E.switch (see doc) and the semantics of the switch reduces to the > semantics of ev, i.e. Maybe I was looking in the wrong place, but I haven't found "the second case of the semantics of E.switch" on your website. In fact, the way I learned about React.E.switch was from the .mli-style webpage on your website, and by trial and error. > Pure equational reasoning, it's not that hard, or is it ? Less than semi-algebraic geometry. More seriously, the point was not understanding why it failed. I came to the same conclusions from empirical evidence. The point was how to overcome it. And while I do not doubt that your documentation is rather explicit, I was nevertheless confused by your fixed point operators, and thus rather reluctant to use them. The example on your website: > let history ?(eq = ( = )) s = > let push v = function > | [] -> [ v ] > | v' :: _ as l when eq v v' -> l > | l -> v :: l > in > let define h = > let h' = S.l2 push s h in > h', h' > in > S.fix [] define One thing that really troubles me, is that I do not understand why define returns a couple of two identical element. And the typing of E.fix is rather confusing: > val fix : ('a React.event -> 'a React.event * 'b) -> 'b Why do we return a 'b type with E.fix? While the webpage mentions this dependence on the value at t-dt, it's quite hard to infer from the use of the fix point operator in the example how it's really supposed to behave and to be called. Clarifying these issues would be welcome. All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-09 18:24 ` Guillaume Yziquel @ 2009-12-10 8:24 ` Daniel Bünzli 2009-12-10 21:41 ` Guillaume Yziquel 0 siblings, 1 reply; 15+ messages in thread From: Daniel Bünzli @ 2009-12-10 8:24 UTC (permalink / raw) To: guillaume.yziquel; +Cc: OCaml List > Maybe I was looking in the wrong place, but I haven't found "the second case > of the semantics of E.switch" on your website. In fact, the way I learned > about React.E.switch was from the .mli-style webpage on your website, and by > trial and error. Here : http://erratique.ch/software/react/doc/React.E.html#VALswitch Second bullet. > One thing that really troubles me, is that I do not understand why define > returns a couple of two identical element. And the typing of E.fix is rather > confusing: > >> val fix : ('a React.event -> 'a React.event * 'b) -> 'b Yes it's confusing. It's here to allow to define mutually recursive definitions and still expose them to the outside world. It is also usefull if you have other values that depend on the delayed value and you want to expose them to the outside world. There are example of this in the breakout.ml example. [snip] I tried to rexeplain E.fix and S.fix but I came up with what's written in their documentation sorry. Daniel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-10 8:24 ` Daniel Bünzli @ 2009-12-10 21:41 ` Guillaume Yziquel 2009-12-11 1:22 ` Daniel Bünzli 0 siblings, 1 reply; 15+ messages in thread From: Guillaume Yziquel @ 2009-12-10 21:41 UTC (permalink / raw) To: Daniel Bünzli; +Cc: OCaml List Daniel Bünzli a écrit : >> Maybe I was looking in the wrong place, but I haven't found "the second case >> of the semantics of E.switch" on your website. In fact, the way I learned >> about React.E.switch was from the .mli-style webpage on your website, and by >> trial and error. > > Here : > > http://erratique.ch/software/react/doc/React.E.html#VALswitch > > Second bullet. I think you should really make a direct link to this page from either http://erratique.ch/software/react/doc/React.html or http://erratique.ch/software/react/doc/index.html because I've been on your website quite a few times, and it's the first time I see this page. (Which is really useful). >> One thing that really troubles me, is that I do not understand why define >> returns a couple of two identical element. And the typing of E.fix is rather >> confusing: >> >>> val fix : ('a React.event -> 'a React.event * 'b) -> 'b > > Yes it's confusing. It's here to allow to define mutually recursive > definitions and still expose them to the outside world. It is also > usefull if you have other values that depend on the delayed value and > you want to expose them to the outside world. There are example of > this in the breakout.ml example. > > [snip] I tried to rexeplain E.fix and S.fix but I came up with what's > written in their documentation sorry. > > Daniel Same comment for E.fix as for E.switch. I have never seen its documentation before. It's much much clearer now. All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: Recursion on React.events. 2009-12-10 21:41 ` Guillaume Yziquel @ 2009-12-11 1:22 ` Daniel Bünzli 0 siblings, 0 replies; 15+ messages in thread From: Daniel Bünzli @ 2009-12-11 1:22 UTC (permalink / raw) To: guillaume.yziquel; +Cc: OCaml List > I think you should really make a direct link to this page from either Well, there's one thing I cannot do for you is to learn to browse. There are at least 11 direct links to these pages from React.html, without counting the two direct module definition links which I thought you would have clicked at some point. Now I'm very impressed you went that far ignoring all this documentation. About Lwt, I'm open to any suggestion to make react easier to interact with (however at the moment I don't want react to depend on Lwt). Lwt is also something I want to get into at some point but now is not the time. I saw some kind of support was added to Lwt for react. If the authors of Lwt are on this list, maybe they want to comment on what their vision is. Best, Daniel ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-12-11 12:16 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-12-09 2:40 Recursion on React.events Guillaume Yziquel 2009-12-09 3:22 ` Guillaume Yziquel 2009-12-09 4:25 ` Daniel Bünzli 2009-12-09 18:47 ` Guillaume Yziquel 2009-12-10 8:39 ` Daniel Bünzli 2009-12-09 7:53 ` Daniel Bünzli 2009-12-09 11:23 ` [Caml-list] " Richard Jones 2009-12-09 18:01 ` Guillaume Yziquel 2009-12-10 3:38 ` Daniel Bünzli 2009-12-10 22:24 ` Guillaume Yziquel 2009-12-11 12:16 ` Jérémie Dimino 2009-12-09 18:24 ` Guillaume Yziquel 2009-12-10 8:24 ` Daniel Bünzli 2009-12-10 21:41 ` Guillaume Yziquel 2009-12-11 1:22 ` Daniel Bünzli
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox