[Caml-list] a push style event combinator

2011-09-15 Thread Satoshi Ogasawara
Hello,

I'd like to announce the release of PEC, a push style event combinator.

  PEC : https://github.com/osiire/Pec

This small module(about 350 LOC) provides

- a composable event.
- map, choose, never, join and several useful functions.
- immediate reactions corresponds sending data to events.
- no memory leaks.

I think PEC is useful to write event driven systems. The signature is as 
follows.

type 'a event

(** [make ()] makes a new event and sender function.*)
val make : unit -> 'a event * ('a -> unit)
val map : ('a -> 'b) -> 'a event -> 'b event

(** [choose l] is a event which will be raised when one of specified events 
occurred. *)
val choose : 'a event list -> 'a event
val never : 'a event
(** [join ee] is a event which will be raised when a inner event occurred.
"Inner event" is a event comes from outer event [ee]. *)
val join : 'a event event -> 'a event
(** [bind e f] is [join (map f e)] *)
val bind : 'a event -> ('a -> 'b event) -> 'b event
val scan : ('a -> 'b -> 'a) -> 'a -> 'b event -> 'a event
val filter : ('a -> bool) -> 'a event -> 'a event
val filter_map : ('a -> 'b option) -> 'a event -> 'b event
val zip : 'a event -> 'b event -> ('a * 'b) event
val take_while : ('a -> bool) -> 'a event -> 'a event
val take_while_in : ('a -> bool) -> 'a event -> 'a event
val take_n : int -> 'a event -> 'a event
val once : 'a event -> 'a event
val drop_while : ('a -> bool) -> 'a event -> 'a event
val drop_n : int -> 'a event -> 'a event
val delay : int -> 'a event -> 'a event
val pairwise : 'a event -> ('a * 'a) event

(** [subscribe f e] attaches the [f] to the specified event.
The [f] will be called when the [e] will occurred. *)
val subscribe : ('a -> unit) -> 'a event -> unit

(** [value e] returns a reference cell which store a latest value *)
val value : 'a -> 'a event -> 'a ref

(** [run ()] runs PEC event system and returns a number of queuing size of 
sended data. *)
val run : unit -> int


e.g.
 Using PEC, you can write a drag event from mouse events like this.

let (+>) f g = g f
(* E is PEC module *)
let dragging mouse_down mouse_up mouse_move =
  E.bind mouse_down (fun dloc -> E.choose [
E.map (fun uloc -> `Drop (dloc, uloc)) mouse_up;
E.map (fun mloc -> `Drag (dloc, mloc)) mouse_move;
  ]
  +> E.take_while_in (function `Drop _ -> false | _ -> true))


Regards,
 ogasawara

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] a push style event combinator

2011-09-15 Thread Satoshi Ogasawara

(2011/09/15 23:45), Philippe Veber wrote:

Thank you for releasing your library, it looks really interesting !


Thank you for your reply.


How would you compare it with react (http://erratique.ch/software/react) which, 
AFAIU, can
be used for similar purposes ? At least I can see there is no notion of signal 
(continuous
function of time) in PEC (or maybe signals can be emulated somehow ?). Also 
could you
comment on the 'no memory leaks' feature ?


Yes, both the react and PEC can be used for similar purpose. But there are some
different points between the two libraries.

 - PEC is "subscribe" centered. If you leave a event alone without subscribing,
   no actions will be occurred even if you send data to the event.
   The react library's system always runs update cycle at sending data to 
events.

 - Instead of signal, PEC have "value" function. "value" function attaches a 
event and
   returns a reference cell which contains latest occurrence data of the event.
   I think it's enough because signal is only terminal point of reactive events.

 - PEC's inside representation of event is not dependency graph but just nested 
variants.
   Let me assume a event A depends on other event B. In case of using 
dependency graph,
   event B has pointer of event A. This caused difficulty about memory leaks 
because
   there is no good timing to free the event A.
   PEC's event is just a nested variants. It means that event A has pointer of 
event B.
   So the event A will be garbage-collected automatically when the reference to 
the
   event A from application layer disappeared. That is the reason why "no memory 
leaks".


Regards,
 ogasawara



cheers,
   Philippe.


2011/9/15 Satoshi Ogasawara mailto:ogasaw...@itpl.co.jp>>

Hello,

I'd like to announce the release of PEC, a push style event combinator.

  PEC : https://github.com/osiire/Pec

This small module(about 350 LOC) provides

- a composable event.
- map, choose, never, join and several useful functions.
- immediate reactions corresponds sending data to events.
- no memory leaks.

I think PEC is useful to write event driven systems. The signature is as 
follows.

type 'a event

(** [make ()] makes a new event and sender function.*)
val make : unit -> 'a event * ('a -> unit)
val map : ('a -> 'b) -> 'a event -> 'b event

(** [choose l] is a event which will be raised when one of specified events 
occurred. *)
val choose : 'a event list -> 'a event
val never : 'a event
(** [join ee] is a event which will be raised when a inner event occurred.
"Inner event" is a event comes from outer event [ee]. *)
val join : 'a event event -> 'a event
(** [bind e f] is [join (map f e)] *)
val bind : 'a event -> ('a -> 'b event) -> 'b event
val scan : ('a -> 'b -> 'a) -> 'a -> 'b event -> 'a event
val filter : ('a -> bool) -> 'a event -> 'a event
val filter_map : ('a -> 'b option) -> 'a event -> 'b event
val zip : 'a event -> 'b event -> ('a * 'b) event
val take_while : ('a -> bool) -> 'a event -> 'a event
val take_while_in : ('a -> bool) -> 'a event -> 'a event
val take_n : int -> 'a event -> 'a event
val once : 'a event -> 'a event
val drop_while : ('a -> bool) -> 'a event -> 'a event
val drop_n : int -> 'a event -> 'a event
val delay : int -> 'a event -> 'a event
val pairwise : 'a event -> ('a * 'a) event

(** [subscribe f e] attaches the [f] to the specified event.
The [f] will be called when the [e] will occurred. *)
val subscribe : ('a -> unit) -> 'a event -> unit

(** [value e] returns a reference cell which store a latest value *)
val value : 'a -> 'a event -> 'a ref

(** [run ()] runs PEC event system and returns a number of queuing size of 
sended data. *)
val run : unit -> int


e.g.
  Using PEC, you can write a drag event from mouse events like this.

let (+>) f g = g f
(* E is PEC module *)
let dragging mouse_down mouse_up mouse_move =
  E.bind mouse_down (fun dloc -> E.choose [
E.map (fun uloc -> `Drop (dloc, uloc)) mouse_up;
E.map (fun mloc -> `Drag (dloc, mloc)) mouse_move;
  ]
  +> E.take_while_in (function `Drop _ -> false | _ -> true))


Regards,
  ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs





--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



[Caml-list] [ANN] PEC ver. 1.1

2012-04-17 Thread Satoshi Ogasawara
Hello lists,

I'm please to announce release PEC version 1.1, a push-based event combinator 
library
which is helpful to write event driven systems with purely functional style.

 https://github.com/osiire/Pec

PEC is similar to React library but there are some different points.

- PEC's update cycle is separated from sending events.
  You can send a value to event during update cycle.

- PEC doesn't hold any pointer(including weak one) to event until the
  event will be subscribed.

- All PEC's signal are switchable. 'switch' means you can replace dependency
  of a signal keeping signals depends on the signal unchanged.

You can see sample codes to use PEC.

https://github.com/osiire/Pec/blob/master/test/

Regards,
 ogasawara

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-17 Thread Satoshi Ogasawara

(2012/04/18 2:52), Adrien wrote:

I haven't been able to take more than a close look at PEC but I'm
interested in it (in particular for the ability to send values to
events during the update cycle).


Thank you for your interest in my library.


I've noticed EventSig.scan: val scan : ('a ->  'b ->  'a) ->  'a ->  'b t ->  
'a t
Is this function like a fold? Is there a particular reason for naming
it "scan" (rather than "fold")?


Because I thought Haskell's scanl is more similar to EventSig.scan than foldl.

scanl : (a -> b -> a) -> a -> [b] -> [a]
foldl : (a -> b -> a) -> a -> [b] -> a

BTW, I have just noticed Event.scan has a bug. The result of scan function 
should
 contain initial value specified second argument, but Event.scan doesn't.
That has been fixed.


Regards,
  Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-17 Thread Satoshi Ogasawara

Hello,

(2012/04/18 4:23), Daniel Bünzli wrote:

- PEC's update cycle is separated from sending events.
You can send a value to event during update cycle.

What's the semantics if you send two different values to an event during an 
update cycle ?


They fires two different event if you send two different value to an event
even if same update cycle. Events send are stored in an event queue,
and they will be poped by 'run' function just like GUI event loop.


- PEC doesn't hold any pointer(including weak one) to event until the
event will be subscribed.

I'm not sure how that's different from react. If an event has no dependents (by which I 
understand your "subscribed"), react doesn't hold any pointer either.


React constructs 'heap' to hold dependency graph inside the library.
let e' = map (fun x -> x + 1) e, the e' and e are weakly pointed by the heap.
PEC doesn't have heap structure in the library. This is a difference.

This difference is important if you want to translate the OCaml event
combinator to javascript because javascript doesn't have weak pointer.


- All PEC's signal are switchable. 'switch' means you can replace dependency
of a signal keeping signals depends on the signal unchanged.

How is that different from react's E.switch/S.switch ?


Almost same except all signals are created though react's S.switch at 
initializing.

It's convenient to design library for dynamic event driven systems. For example,
let me assume a signal of window size property.

type window = {
   size : (int * int) signal;
}

If you want to change the dependency of window.size after initialize the window
keeping signals depends on the size unchanged, there is no way except making 
switch
event at initializing.

type window = {
   size : (int * int) signal;
   size_switch_event : (int * int) event event;
}

I feel it's not convenient. So I decided to embedded the swith_event to inside 
of signals.

Regards,
  Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-18 Thread Satoshi Ogasawara

Hello,

Thank you very much for your prompt reply.

(2012/04/18 16:36), Daniel Bünzli wrote:

1) Thread-safety and compositionality. React has no global data structure.


I'm sorry about my misunderstanding that React has a global structure.


2) Semantic issues. As soon as primitive events are triggered by other 
primitive events you run into the problem of multiple occurences of the same 
event during an update cycle. Now given the synchrony hypothesis of update 
cycles (an update cycle is instantaneous), this is a violation of the semantics 
of events (an event has at most one occurence at any given time t). And then 
people ask you if you can somehow manage the order of updates in an update 
cycle and then you are not doing FRP anymore, you are doing RP. By loosing the 
F you also loose compositionality and the equational reasoning tools provided 
by the denotational semantics of events.


I see that React is implemented with intend to keep good semantics and able to
realize same functions as PEC.
But PEC dose not violate good semantics either. PEC treats only one event at any
given time t. Please see blow code.

module E = Pec.Event.Make (Pec.EventQueue.DefaultQueueM) 
(Pec.EventQueue.DefaultQueueI)
open Printf

let _ =
  let e, sender = E.make () in
  let e' = E.map (fun x -> sender 2; x + 1) e in   (* during update cycle, send 
2. *)
  let _ = E.subscribe (printf "e=%d\n") e in
  let _ = E.subscribe (printf "e'=%d\n") e' in
  sender 1;
  ignore (E.run ());   (* run one event *)
  printf "---\n";
  ignore (E.run ());   (* run one event *)
  printf "end\n"

This program outputs:

e=1
e'=2
---
e=2
e'=3
end

The function (fun x -> sender 2; x + 1) is not purely functional. I see that 
violates
a part of good semantics and composability. But there is no problem of multiple
occurrences of the same event in one update cycle.

To write event driven systems such like GUI sometimes needs a event-event chain
without real-user actions. Sending events during update cycle is something 
unavoidable.


Regarding the absence of Weak usage I'm curious in how you manage the garbage 
collections of events that depend on others.


Yes, weak-pointer-less implementation is one of my purpose. The key point is
that dependency of events are represented by nested variants.

Best Regards,
  Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-18 Thread Satoshi Ogasawara


First of all, I apologize about my first message. Now I understand React can be
easily adapted to send a value during update cycle by using thunk. To forbid
sending events during update cycle in React is not restriction but design 
choice.

(2012/04/18 22:27), Daniel Bünzli wrote:
> and now what should the value of e be in the next update cycle ? All the options you 
have (keep only the first call to sender, keep only the last call to sender, keep both and 
execute one after the other) break the functional and compositional nature of FRP because 
it violates the semantics of events.


PEC takes the third option. I understand that the evaluation order of update
are problematic.

module E = Pec.Event.Make (Pec.EventQueue.DefaultQueueM) 
(Pec.EventQueue.DefaultQueueI)
open Printf

let _ =
  let e, sender = E.make () in
  let e' = E.map (fun x -> sender 2; x + 1) e in
  let e'' = E.map (fun x -> sender 3; x + 1) e in
  let _ = E.subscribe (printf "e=%d\n") e in
  let _ = E.subscribe (printf "e'=%d\n") e' in
  let _ = E.subscribe (printf "e''=%d\n") e'' in
  sender 1;
  ignore (E.run ());
  printf "---\n";
  ignore (E.run ());
  printf "---\n";
  ignore (E.run ());
  printf "end\n"

This program outputs:

e=1
e'=2
e''=2
---
e=2
e'=3
e''=3
---
e=3
e'=4
e''=4
end

This result rely on order of applying subscribe function. I think any program
depending on the evaluation order of updates are not good one.

But I'm not sure why only sending a value to event breaks functional and compos-
itional nature of FRP. I think all side-effects during update cycle are breaks
functional and compositional nature of FRP too, because the results of both 
programs
are depends on evaluation order of updates.

A:
let e' = E.map (fun x -> sender 1; x + 1) e in
let e'' = E.map (fun x -> sender 2; x + 1) e in

B:
let e' = E.map (fun x -> print_int 1; x + 1) e in
let e'' = E.map (fun x -> print_int 2; x + 1) e in

Are there any special problem in program A? In other word, program B keeps
functional and compositional nature of FRP?


Yes, weak-pointer-less implementation is one of my purpose. The key point is
that dependency of events are represented by nested variants.


That doesn't really answer my question (or at least I don't understand what it 
means).


Inside PEC, "let e' = E.map f e" is just variant instance.

  let map f e = Wrap {
event = e;
wrap = f;
w_latest = None;
  }

Another primitive combinator functions also just makes a variant instance.

  and 'a event =
| Cell : 'a mcell -> 'a event
| Wrap : ('a, 'b) mwrap -> 'b event
| Choose : 'a choose -> 'a event
| Never : 'a event
| Switch : 'a mswitch -> 'a event

So an event value itself is a nested variant instance which can be GCed freely
when user-level references are disappear. (There are no library level 
reference.)

When an event is subscribed, the argument function are set in source events of
subscribed event. This means subscribed events are never GCed until source 
events
are GCed.(or until unsubscribe.)

If one of source events are fired, dependent events marked with subscribe 
functions
are updated. Weak pointer does not needs in that algorithm.


Best Regards,
 Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-19 Thread Satoshi Ogasawara


(2012/04/19 7:32), Daniel Bünzli wrote:

Yes because the semantics of [e] is violated, it has three values at the same 
time, the current value during the update cycle, the value 1 and the value 2. 
Now suppose I reason about the semantics of [e] in this program, it has a 
well-defined outcome *for [e] itself* if I send it a value [v]. However if you 
now add a new module that uses [e] and does :


Thank you for helping me understand with your explanation.

If I understand correctly sending [v] to [e] immediately during update cycle
are violate the semantics because it cause more than one values on one event at
the same time.

Using React,

let e, sender = E.create () in
let e' = E.map (fun x -> Queue.add q (fun () -> sender 1); x + 1) e in
let e'' = E.map (fun x -> Queue.add q (fun () -> sender 2); x + 1) e in

does this code violate the semantics of events? If so, PEC is also unsound.
I'd like to know PEC is unsound or not.

> So if I understand correctly you are doing manual memory management via (un)subscribe 
of the leaves of the dependency tree and instead of having weak "forward" pointers from 
events to their dependents you have regular "backward" pointers from events to the events 
they depend on. Once these leaves are subscribed we can follow them backwards to find out 
what their primitive event set is and understand what needs to be updated along the way.


Yes, exactly.

>It may be an interesting approach to avoid weak pointers but I'd need more thinking to 
convince me it can correctly handles all the dark sides of leaks, fixed point definitions, 
signal initialization and dynamically changing dependency graph. By the way you still need 
to update the events in the correct order/and or only once to prevent glitches, how do you 
achieve that ?


To prevent glitches, PEC distinct one update cycle to another by time identity.
And calculated results are cached for same update cycle.
Update order is straight forward. Just follow from leaf to primitive source 
event.
It's not problem because only one primitive value changes at one update cycle.

Best Regards,
  Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-19 Thread Satoshi Ogasawara


Thank you for helping me understand with your explanation.

Your event semantics has two invariant.

 1. for all e, t : occurrence of [e] at time [t] is one or zero.
 2. if primitive [e] is occurred in time [t], update cycle runs in time [t].

Do you have any experience to proof a theorem against event combination term
by using above axiom and event combinators semantics? I'm interested in this
kind of reasoning.

(2012/04/19 19:31), Daniel Bünzli wrote:

Right. But you still have to maintain some kind of mapping between the 
primitive event and the leaves they may influence to know which ones to update 
when the corresponding primitive event occurs. Do you store that in the 
primitive event itself or do you use a global data structure ?


Primitive events has list of leaves.


Best Regards,
 Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-19 Thread Satoshi Ogasawara


(2012/04/19 19:57), Daniel Bünzli wrote:

Le jeudi, 19 avril 2012 à 12:31, Daniel Bünzli a écrit :
If P1 occurs then you start walking back from L, but you don't know where P1 is 
so you have to walk down every branch until you find P1 and then walk back from 
there up to L to make the update.
Contrast this with (weak) forward pointers: you just start from P1 and walk 
*once* up to L.
Is that correct ?


It's correct. But the performance can be optimized in future I think.

When subscribing a event, we can collect and store information about tree 
structure.
Present implementation discards these information.

Best Regards,
  Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs



Re: [Caml-list] [ANN] PEC ver. 1.1

2012-04-20 Thread Satoshi Ogasawara

(2012/04/19 23:09), Daniel Bünzli wrote:

Do you have any experience to proof a theorem against event combination term
by using above axiom and event combinators semantics? I'm interested in this
kind of reasoning.


In this post I use the semantics and equational reasoning to understand why 
something doesn't happen.

https://sympa-roc.inria.fr/wws/arc/caml-list/2009-12/msg00054.html

(you may have to read the whole thread to fully understand the example).


Thank you for your information. I like this kind of strict reasoning.
I'd like to add some semantics to PEC, too.

Any way, thank you for your educational discussion!

Best Regards,
 Ogasawara

--
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs