caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* 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  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: 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  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: [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: 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-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-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: [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: 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

* 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

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;
as well as URLs for NNTP newsgroup(s).