<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hello,</div><div><br class="webkit-block-placeholder"></div><div>Here is the latest Caml Weekly News, for the week of December 11 to December 18, 2007.</div><div><br class="webkit-block-placeholder"></div><div>The Caml Weekly News will be taking a break next week. Happy holidays!</div><div><br class="webkit-block-placeholder"></div><div>1) CUFP Report Available</div><div>2) New contact address for the hump</div><div>3) First-class typed, direct-style sprintf</div><div>4) objsize-0.1</div><div>5) Jsure 1.0 Javascript checker</div><div>6) "Ref" and copy of functions</div><div>7) OCaml meeting in Paris</div><div>8) Camlp5 release 5.05</div><div><br class="webkit-block-placeholder"></div><div>========================================================================</div><div>1) CUFP Report Available</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/58d732a29f4521ff#83bb57898b9c241c">http://groups.google.com/group/fa.caml/browse_frm/thread/58d732a29f4521ff#83bb57898b9c241c</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Kathleen Fisher announced:</div><div><br class="webkit-block-placeholder"></div><div>Jeremy Gibbons has written a very detailed report on the 2007 &nbsp;&nbsp;</div><div>Commercial Users of Functional Programming Workshop. &nbsp;His report is &nbsp;&nbsp;</div><div>available from the CUFP web page (&lt;<a href="http://cufp.functionalprogramming.com">http://cufp.functionalprogramming.com</a>&gt;)&nbsp;</div><div>as well as from the CUFP google group &nbsp;&nbsp;</div><div>page (&lt;<a href="http://groups.google.com/group/cufp">http://groups.google.com/group/cufp</a>&gt;). &nbsp;Thank you, Jeremy!&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Peter Thiemann and his students are just finishing up the post &nbsp;&nbsp;</div><div>processing of the recordings of the talks, and we are in the process &nbsp;&nbsp;</div><div>of getting those talks loaded onto the web. &nbsp;I'll send a further &nbsp;&nbsp;</div><div>announcement when the talks are available.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>2) New contact address for the hump</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/04a9ab9657fe8341#74a9140a02e15640">http://groups.google.com/group/fa.caml/browse_frm/thread/04a9ab9657fe8341#74a9140a02e15640</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Maxence Guesdon announced:</div><div><br class="webkit-block-placeholder"></div><div>The new (and working) e-mail address to contact the hump administrators is:&nbsp;</div><div>&nbsp;&nbsp;caml-hump "AT" inria.fr&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The Caml Hump:&nbsp;</div><div>&nbsp;&nbsp;&lt;<a href="http://caml.inria.fr//cgi-bin/hump.en.cgi">http://caml.inria.fr//cgi-bin/hump.en.cgi</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>3) First-class typed, direct-style sprintf</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/5fd7b552a8e8b067#53c242b901f557db">http://groups.google.com/group/fa.caml/browse_frm/thread/5fd7b552a8e8b067#53c242b901f557db</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Oleg described:</div><div><br class="webkit-block-placeholder"></div><div>We demonstrate direct-style typed sprintf: sprintf format_spec arg1 arg2 ....&nbsp;</div><div>The type system ensures that the number and the types of format&nbsp;</div><div>specifiers in format_expression agree with the number and the types of&nbsp;</div><div>arg1, etc. Our sprintf and format specifiers are ordinary,&nbsp;</div><div>first-class functions, and so can be passed as arguments or returned&nbsp;</div><div>as results. The format specifiers can also be composed incrementally.&nbsp;</div><div>Unlike Danvy/Filinski's sprintf, the types seem to be simpler.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Recently there has been discussion contrasting the OCaml Printf module&nbsp;</div><div>with Danvy/Filinski's functional unparsing. The latter can be&nbsp;</div><div>implemented as a pure library function, requiring no special support&nbsp;</div><div>from the compiler. It does require writing the format specifiers in&nbsp;</div><div>the continuation-passing style, which makes types huge and&nbsp;</div><div>errors very difficult to find. Perhaps less known that&nbsp;</div><div>Danvy/Filinski's functional unparsing has a direct-style&nbsp;</div><div>counter-part. It is particularly elegant and simple: the whole&nbsp;</div><div>implementation takes only four lines of code. The various&nbsp;</div><div>implementations of typed sprintf are lucidly and insightfully&nbsp;</div><div>described in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&lt;<a href="http://pllab.is.ocha.ac.jp/~asai/papers/tr07-1.ps.gz">http://pllab.is.ocha.ac.jp/~asai/papers/tr07-1.ps.gz</a>&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Alas, the elegant sprintf requires control operators supporting both&nbsp;</div><div>answer-type modification and polymorphism. The corresponding calculus&nbsp;</div><div>has been presented in the recent APLAS 2007 paper by Asai and&nbsp;</div><div>Kameyama. &nbsp;They have proven greatly desirable properties of their&nbsp;</div><div>calculus: strong type soundness, principal types, the existence of a&nbsp;</div><div>type inference algorithm, preservation of types and equality through&nbsp;</div><div>CPS translation, confluence, strong normalization for the subcalculus&nbsp;</div><div>without fix.&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&lt;<a href="http://logic.cs.tsukuba.ac.jp/~kam/paper/aplas07.pdf">http://logic.cs.tsukuba.ac.jp/~kam/paper/aplas07.pdf</a>&gt;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&lt;<a href="http://pllab.is.ocha.ac.jp/~asai/papers/aplas07slide.pdf">http://pllab.is.ocha.ac.jp/~asai/papers/aplas07slide.pdf</a>&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>At that time, only prototype implementation was available, in a&nbsp;</div><div>private version of mini-ML. Yesterday, a straightforward Haskell98&nbsp;</div><div>implementation of the calculus emerged, based on parameterized monads:&nbsp;</div><div>&nbsp;&nbsp;&lt;<a href="http://www.haskell.org/pipermail/haskell/2007-December/020034.html">http://www.haskell.org/pipermail/haskell/2007-December/020034.html</a>&gt;&nbsp;</div><div>It includes sprintf.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>OCaml already has delimited control operators, in the delimcc&nbsp;</div><div>library. Those operators, too, support polymorphism. They are&nbsp;</div><div>different however, supporting multiple typed prompts, but the fixed&nbsp;</div><div>answer type (which is the type of the prompt). It has not been known&nbsp;</div><div>until today if the quantity of the prompts can make up for their&nbsp;</div><div>quality: can multi-prompt shift/reset (or, cupto) _emulate_ the&nbsp;</div><div>modification of the answer-type. We now know that the answer is yes.&nbsp;</div><div>Many elegant applications of shift/reset become possible; in&nbsp;</div><div>particular, `shift (fun k -&gt; k)' becomes typeable. The latter has many&nbsp;</div><div>applications, e.g., in web form programming and linguistics.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The full implementation and many tests (of sprintf) are available at&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&lt;<a href="http://okmij.org/ftp/ML/sprintf-cupto.ml">http://okmij.org/ftp/ML/sprintf-cupto.ml</a>&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The following are a few notable excerpts. First are the definitions of&nbsp;</div><div>answer-type modifying, polymorphic shift/reset. &nbsp;Unlike the&nbsp;</div><div>fixed-answer-type shift/reset, which have one prompt, shift2/reset2&nbsp;</div><div>have two prompts, for the two answer types (before and after the&nbsp;</div><div>modification).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let reset2 f =&nbsp;</div><div>&nbsp;&nbsp;let p1 = new_prompt () in&nbsp;</div><div>&nbsp;&nbsp;let p2 = new_prompt () in&nbsp;</div><div>&nbsp;&nbsp;push_prompt p1 (fun () -&gt; abort p2 (f (p1,p2)));;&nbsp;</div><div>val reset2 : ('a Delimcc.prompt * 'b Delimcc.prompt -&gt; 'b) -&gt; 'a = &lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let shift2 (p1,p2) f =&nbsp;</div><div>&nbsp;&nbsp;shift p1 (fun k -&gt; fun x -&gt;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;push_prompt p2 (fun () -&gt; f k x; failwith "omega"));;&nbsp;</div><div>val shift2 :&nbsp;</div><div>&nbsp;&nbsp;('a -&gt; 'b) Delimcc.prompt * 'b Delimcc.prompt -&gt;&nbsp;</div><div>&nbsp;&nbsp;(('c -&gt; 'a -&gt; 'b) -&gt; 'a -&gt; 'd) -&gt; 'c = &lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>At first sight, these definitions seem trivial. At the second sight,&nbsp;</div><div>they seem outright wrong, as 'abort p2' seem to be executed before the&nbsp;</div><div>corresponding prompt p2 is pushed. Hopefully, the fifth sight will&nbsp;</div><div>show that the definitions are indeed simple and do what they are&nbsp;</div><div>supposed to.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>We can write the following append function (Sec 2.1 of Asai and&nbsp;</div><div>Kameyama's APLAS paper)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let rec append lst prompts =&nbsp;</div><div>&nbsp;&nbsp;match lst with&nbsp;</div><div>&nbsp;&nbsp;| [] -&gt; shift2 prompts (fun k l -&gt; k l)&nbsp;</div><div>&nbsp;&nbsp;| a::rest -&gt; a :: append rest prompts;;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>whose inferred type&nbsp;</div><div>&nbsp;&nbsp; 'a list -&gt; ('a list -&gt; 'b) Delimcc.prompt * 'b Delimcc.prompt -&gt; 'a list&nbsp;</div><div>clearly shows both the polymorphism (in 'b) and the answer-type&nbsp;</div><div>modification from 'b to 'a list -&gt; 'b.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Here's the typed sprintf:&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let test3 = sprintf (lit "The value of " ^^ fmt str ^^ lit " is " ^^ fmt int);;&nbsp;</div><div>&nbsp;&nbsp; val test3 : string -&gt; int -&gt; string = &lt;fun&gt;&nbsp;</div><div>let test3r = test3 "x" 1;;&nbsp;</div><div>&nbsp;&nbsp; val test3r : string = "The value of x is 1"&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>We can write this test in the following way, to demonstrate that&nbsp;</div><div>sprint and format specifiers are first-class and that the format&nbsp;</div><div>specification can be composed incrementally.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let test3' =&nbsp;</div><div>&nbsp;&nbsp;let format_spec1 = lit "The value of " ^^ fmt str ^^ lit " is " in&nbsp;</div><div>&nbsp;&nbsp;let format_spec = format_spec1 ^^ fmt int in&nbsp;</div><div>&nbsp;&nbsp;let applyit f x = f x in&nbsp;</div><div>&nbsp;&nbsp;let formatter = applyit sprintf format_spec in&nbsp;</div><div>&nbsp;&nbsp;formatter "x" 1;;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Here are the (inferred) types of format specifiers and of their compositions:&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;# lit "xx";;&nbsp;</div><div>&nbsp;- : '_a Delimcc.prompt * '_a Delimcc.prompt -&gt; string = &lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;# fmt int;;&nbsp;</div><div>&nbsp;- : (int -&gt; '_a) Delimcc.prompt * '_a Delimcc.prompt -&gt; string = &lt;fun&gt;&nbsp;</div><div>&nbsp;# fmt str;;&nbsp;</div><div>&nbsp;- : (string -&gt; '_a) Delimcc.prompt * '_a Delimcc.prompt -&gt; string = &lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;# fmt int ^^ lit "xx";;&nbsp;</div><div>&nbsp;- : (int -&gt; '_a) Delimcc.prompt * '_a Delimcc.prompt -&gt; string = &lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;# fmt int ^^ fmt str;;&nbsp;</div><div>&nbsp;- : (int -&gt; string -&gt; '_a) Delimcc.prompt * '_a Delimcc.prompt -&gt; string =&lt;fun&gt;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The type of (fmt int ^^ fmt str) clearly shows the answer-type&nbsp;</div><div>modification. One can read this as follows: given prompts, the&nbsp;</div><div>expression computes a string upon the hypotheses 'int' and 'string' in&nbsp;</div><div>that order.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>4) objsize-0.1</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/069b8cee302e699e#5c699ef3f5c71389">http://groups.google.com/group/fa.caml/browse_frm/thread/069b8cee302e699e#5c699ef3f5c71389</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Dmitry Grebeniuk announced:</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;&nbsp;Some time ago there was a discussion about measuring&nbsp;</div><div>sizes of ocaml values. &nbsp;I've got some "round tuits" and&nbsp;</div><div>released a library that I use in my programs for some&nbsp;</div><div>years. &nbsp;Maybe it will be useful for other people too.&nbsp;</div><div>&nbsp;&nbsp;It is better than pure ocaml solutions because it&nbsp;</div><div>doesn't build hash table of visited values, and it uses&nbsp;</div><div>two bits for each visited value in worst case (but in my&nbsp;</div><div>practice it used no more than 120kb of additional memory&nbsp;</div><div>when I measured sizes of 300Mb-values).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Readme: &nbsp;&lt;<a href="http://89.187.37.10/gds/objsize/README">http://89.187.37.10/gds/objsize/README</a>&gt;&nbsp;</div><div>Tarball: &lt;<a href="http://89.187.37.10/gds/objsize/objsize-0.1.tar.gz">http://89.187.37.10/gds/objsize/objsize-0.1.tar.gz</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** Jon Harrop said and Dmitry Grebeniuk replied:</div><div><br class="webkit-block-placeholder"></div><div>&gt; This doesn't seem to work on 64-bit. First I get:&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;&nbsp;Thanks for testing, now it works on your platform too.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Readme: &nbsp;&lt;<a href="http://89.187.37.10/gds/objsize/README">http://89.187.37.10/gds/objsize/README</a>&gt;&nbsp;</div><div>Tarball: &lt;<a href="http://89.187.37.10/gds/objsize/objsize-0.11.tar.gz">http://89.187.37.10/gds/objsize/objsize-0.11.tar.gz</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>5) Jsure 1.0 Javascript checker</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/b4a7613afd790c6f#5f66bbade9416f59">http://groups.google.com/group/fa.caml/browse_frm/thread/b4a7613afd790c6f#5f66bbade9416f59</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Berke Durak announced:</div><div><br class="webkit-block-placeholder"></div><div>Jsure is a "lint" for Javascript, which is also known as Ecmascript.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>It checks syntax and a little bit of semantics (it's difficult to do&nbsp;</div><div>anything more sophisticated with real-world Javascript short of&nbsp;</div><div>interpreting it).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>We have been quite happy with it at Exalead for a few months now and so&nbsp;</div><div>we decided to release it under the LGPL.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>It is used daily to check the code in the Baagz &lt;<a href="http://baagz.com/">http://baagz.com/</a>&gt; project.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>It uses Aurochs as its parser (&lt;<a href="http://aurochs.fr/">http://aurochs.fr/</a>&gt;).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>You can get it at:&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>&nbsp;&nbsp; &lt;<a href="http://aurochs.fr/jsure.html">http://aurochs.fr/jsure.html</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>6) "Ref" and copy of functions</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/fbf1535f57fd5115#df8d80d702b7f1a5">http://groups.google.com/group/fa.caml/browse_frm/thread/fbf1535f57fd5115#df8d80d702b7f1a5</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Pierre-Evariste Dagand asked:</div><div><br class="webkit-block-placeholder"></div><div>I'm looking for advices about a "clean way" of doing something which,&nbsp;</div><div>by design, isn't. So, let states the problem.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>I'm doing a combinator library based on Arrows for a Yampa-like system :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>type ('a,'b) arrow = Arrow of ( 'a -&gt; 'b )&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Thus, I can instantiate an arrow with :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let arr f = Arrow ( f )&nbsp;</div><div>val arr : ('a -&gt; 'b) -&gt; ('a, 'b) arrow&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Then, I have, for example, the composition of arrows :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let (&gt;&gt;&gt;) (Arrow f) (Arrow g) =Arrow ( fun &nbsp;c -&gt; g &nbsp;( f &nbsp;c ) )&nbsp;</div><div>val ( &gt;&gt;&gt; ) : ('a, 'b) arrow -&gt; ('b, 'c) arrow -&gt; ('a, 'c) arrow&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Right here, everything plays well (excepted some weak type variables&nbsp;</div><div>issues but that's not a big deal).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>But (and that's here that the trouble is) I need a "loop" combinator,&nbsp;</div><div>that I wrote this way :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let loop init (Arrow f) =&nbsp;</div><div>&nbsp;&nbsp;let state = ref init in&nbsp;</div><div>&nbsp;&nbsp; &nbsp;Arrow (&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;fun c -&gt;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;let new_state , output = f ( !state , c ) in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;state := new_state;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;output&nbsp;</div><div>&nbsp;&nbsp; &nbsp;)&nbsp;</div><div>val loop : 'a -&gt; ('a * 'b, 'a * 'c) arrow -&gt; ('b, 'c) arrow&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Finally, I can write a small arrow &nbsp;:&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let arr_counter = loop 0 ( arr ( fun ( counter , x ) -&gt; counter+1 ,&nbsp;</div><div>counter+x ) )&nbsp;</div><div>let arr_double = arr ( fun x -&gt; 2*x )&nbsp;</div><div>let arr_my_small_arrow = arr_counter &gt;&gt;&gt; arr_double&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>And I execute it with :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let run (Arrow f) input =&nbsp;</div><div>&nbsp;&nbsp;f &nbsp;input&nbsp;</div><div>val run : ('a, 'b) arrow -&gt; 'a -&gt; 'b&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>And it works. Right.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>But now, I would like to be able to "copy" a built arrow and to be&nbsp;</div><div>able to execute the copy without side-effecting on the first one.&nbsp;</div><div>Obviously, I cannot do that in this implementation.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>My current solution is really *ugly* :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let arrow_string = Marshal.to_string arrow [ Marshal.No_sharing ;&nbsp;</div><div>Marshal.Closures ]&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Then I "Marshal.from_string arrow_string". I'm not even sure if it&nbsp;</div><div>will not blow out of my hands with "strange" things in the Ref cell.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>I'm aware of implementations in CPS but I use to think that it has a&nbsp;</div><div>performance cost that I'm not ready to pay (I'm fighting against a C++&nbsp;</div><div>code so...).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>So if someone knows an elegant solution to my problem (if someone has&nbsp;</div><div>read this mail until here), please let me know :-)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Best regards,&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>P.S.: For those who are just curious, these combinators are used in a&nbsp;</div><div>functional-reactive library for Peer-to-Peer overlays programming.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** Oleg suggested:</div><div><br class="webkit-block-placeholder"></div><div>If you like using the mutable state, perhaps you might find the&nbsp;</div><div>following code helpful. The key idea is packaging the clone function&nbsp;</div><div>along with the arrow. There is no longer any need in any unsafe&nbsp;</div><div>features. The lesson from our tagless final APLAS paper is that many&nbsp;</div><div>things are significantly easier if we do the work at the production&nbsp;</div><div>site rather than at the consumption site.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>(* The first component is the arrow itself, the second one is the clone&nbsp;</div><div>&nbsp;&nbsp; function*)&nbsp;</div><div>type ('a,'b) arrow = {arrow: 'a -&gt; 'b; clone: unit -&gt; ('a,'b) arrow};;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let rec arr f = {arrow = f; clone = fun () -&gt; arr f};;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let rec (&gt;&gt;&gt;) f g = {arrow = (fun c -&gt; g.arrow (f.arrow c));&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clone = (fun () -&gt; f.clone () &gt;&gt;&gt; g.clone ())};;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>(* Here, our clone function uses the initial state rather than the&nbsp;</div><div>current state. It is trivial to clone from the current state, if&nbsp;</div><div>desired.*)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let rec loop init f =&nbsp;</div><div>&nbsp;&nbsp;let state = ref init in&nbsp;</div><div>&nbsp;&nbsp;{arrow =&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;(fun c -&gt;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;let new_state , output = f.arrow ( !state , c ) in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;state := new_state;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;output);&nbsp;</div><div>&nbsp;&nbsp; clone = (fun () -&gt; loop init (f.clone ()))};;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let arr_counter = loop 0 (arr (fun (counter, x) -&gt; counter+1 ,counter+x));;&nbsp;</div><div>let arr_double = arr (fun x -&gt; 2*x);;&nbsp;</div><div>let arr_my_small_arrow = arr_counter &gt;&gt;&gt; arr_double;;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let run f input = let v1 = f.arrow input in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;let v2 = f.arrow input in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(v1,v2);;&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let test1 = run arr_my_small_arrow 10;;&nbsp;</div><div>&nbsp;&nbsp;val test1 : int * int = (20, 22)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let test2 = run arr_my_small_arrow 10;;&nbsp;</div><div>&nbsp;&nbsp;val test2 : int * int = (24, 26) &nbsp;(*obviously, counter keeps&nbsp;</div><div>&nbsp;&nbsp;counting *)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let test3 = run (arr_my_small_arrow.clone ()) 10;;&nbsp;</div><div>val test3 : int * int = (20, 22) &nbsp;(* cloning `resets' the counter *)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** Jacques Garrigue also suggested:</div><div><br class="webkit-block-placeholder"></div><div>Here is yet another solution, using objects, which actually combines&nbsp;</div><div>Zheng's and Oleg's ideas. That is, it separates state and function,&nbsp;</div><div>but provides only access to state through a cloning method, so that it&nbsp;</div><div>is completely type safe. This is just what objects are good at!&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>class ['a,'b] arrow (f : 'a -&gt; 'b) =&nbsp;</div><div>&nbsp;&nbsp;object (self) method call = f method copy = self end&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let (&gt;&gt;&gt;) rf rg : ('a,'b) arrow =&nbsp;</div><div>&nbsp;&nbsp;object&nbsp;</div><div>&nbsp;&nbsp; &nbsp;val rf : ('a,'c) arrow = rf&nbsp;</div><div>&nbsp;&nbsp; &nbsp;val rg : ('c,'b) arrow = rg&nbsp;</div><div>&nbsp;&nbsp; &nbsp;method call x = rg#call (rf#call x)&nbsp;</div><div>&nbsp;&nbsp; &nbsp;method copy = {&lt; rf = rf#copy; rg = rg#copy &gt;}&nbsp;</div><div>&nbsp;&nbsp;end&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let loop init rf : ('b,'c) arrow =&nbsp;</div><div>&nbsp;&nbsp;object&nbsp;</div><div>&nbsp;&nbsp; &nbsp;val mutable state = init&nbsp;</div><div>&nbsp;&nbsp; &nbsp;val rf : ('a*'b,'a*'c) arrow = rf&nbsp;</div><div>&nbsp;&nbsp; &nbsp;method call x =&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;let state', y = rf#call (state, x) in&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;state &lt;- state'; y&nbsp;</div><div>&nbsp;&nbsp; &nbsp;method copy = {&lt; rf = rf#copy &gt;}&nbsp;</div><div>&nbsp;&nbsp;end&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>let arr = new arrow&nbsp;</div><div>let arr_counter = loop 0 (arr (fun (counter,x) -&gt; counter+1, counter+x))&nbsp;</div><div>let arr_double = arr (fun x -&gt; 2*x)&nbsp;</div><div>let arr_my_small_arrow = arr_counter &gt;&gt;&gt; arr_double&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The key here is the {&lt; ... &gt;} construct, which creates a shallow copy&nbsp;</div><div>of an object, eventually with some fields changed. As a result, in&nbsp;</div><div>loop there is no need to handle the state explicitly: the state field&nbsp;</div><div>in the copied object will be distinct from the state field in the&nbsp;</div><div>original object. On the other hand, you must explicitly update fields&nbsp;</div><div>holding arrows, since the copy is shallow. Note that the explicit&nbsp;</div><div>"val" fields are needed to allow updating their contents when copying.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>One difference with Oleg's approach is that we take a copy of the&nbsp;</div><div>original object, rather than creating a completely new record. In this&nbsp;</div><div>case, this doesn't mean much, since there is no extra computation&nbsp;</div><div>involved. Still, the state after copying is not the original but the&nbsp;</div><div>current one. And this may matter more if the construction is more&nbsp;</div><div>complicated.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** Pierre-Evariste Dagand replied:</div><div><br class="webkit-block-placeholder"></div><div>Yet another nice solution I would never have imagined :-)&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>And the performance is quite good :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>1.428032 microseconds on my small benchmark&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>(the unsafe Ref implantation takes 0.75 microseconds while the CPS&nbsp;</div><div>implantation takes 2.7 microseconds).&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Nevertheless, I have carried out my benchmark on Oleg's implementation&nbsp;</div><div>and find an impressive performance :&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>0.74 microseconds !&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Now, I will re-write my combinators and see which style better suits my needs.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** Pierre-Evariste Dagand finally added:</div><div><br class="webkit-block-placeholder"></div><div>Finally, impressed by the speed of the record solution, I have&nbsp;</div><div>re-written the whole library with records.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>I have measured the performance of this implementation against the&nbsp;</div><div>Ref-based one on "real" code. Thus, I have simulated my Chord [1]&nbsp;</div><div>implementation with a simulator instrumented such that it drops the&nbsp;</div><div>processing time for each arrow processing.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>The results can be found at [2].&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>In a nutshell : the record solution has a negligible overhead compared&nbsp;</div><div>to the Ref solution.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Thanks all,&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>[1]: &lt;<a href="http://pdos.csail.mit.edu/chord/">http://pdos.csail.mit.edu/chord/</a>&gt;&nbsp;</div><div>[2]: &lt;<a href="http://perso.eleves.bretagne.ens-cachan.fr/~dagand/projets/opis/processing_speed_records.pdf">http://perso.eleves.bretagne.ens-cachan.fr/~dagand/projets/opis/processing_speed_records.pdf</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>7) OCaml meeting in Paris</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/844f6a6880371cbd#8f748cc03a025c4f">http://groups.google.com/group/fa.caml/browse_frm/thread/844f6a6880371cbd#8f748cc03a025c4f</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** It the middle of a thread, Berke Durak said:</div><div><br class="webkit-block-placeholder"></div><div>I agree. &nbsp;I think Ocamlfind and Godi are nice pieces of work, and it&nbsp;</div><div>certainly would be better if we could integrate existing systems.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>We all love Ocaml, but there seems to be an important problem with it.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Unlike most programming languages of similar magnitude, Ocaml doesn't&nbsp;</div><div>have a developer conference where its users could meet face-to-face and&nbsp;</div><div>discuss these kind of things... &nbsp;(or did I miss something?) &nbsp;If not, we&nbsp;</div><div>should organize one.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Ocaml users span half a dozen continents but we could start with a small&nbsp;</div><div>gathering in Paris. &nbsp;I'd suggest late January.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>We could then discuss distribution, building, packaging and other&nbsp;</div><div>issues; &nbsp;and publish guidelines for a "request for implementation" --&nbsp;</div><div>things we would like to see in an integrated compilation and package&nbsp;</div><div>manager.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>People would then implement different solutions and we could gather two&nbsp;</div><div>months later to evaluate the proposals.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Does anyone have a proposal for a gathering place?</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>** The editor said:</div><div><br class="webkit-block-placeholder"></div><div>There have been many replied, suggesting dates and places. Please follow&nbsp;</div><div>the archive link above if you are interested.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>8) Camlp5 release 5.05</div><div>Archive: &lt;<a href="http://groups.google.com/group/fa.caml/browse_frm/thread/bde6e55ecd4ba192#7c2ef011bd661100">http://groups.google.com/group/fa.caml/browse_frm/thread/bde6e55ecd4ba192#7c2ef011bd661100</a>&gt;</div><div>------------------------------------------------------------------------</div><div>** Daniel de Rauglaudre announced:</div><div><br class="webkit-block-placeholder"></div><div>New release of Camlp5: 5.05&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Changes:&nbsp;</div><div>&nbsp;&nbsp;- added function Pcaml.quotation_location returning, in quotation&nbsp;</div><div>&nbsp;&nbsp; &nbsp;expanders, the location of the quotation in the source file.&nbsp;</div><div>&nbsp;&nbsp;- added generation of the file META for ocamlfind (built in&nbsp;</div><div>&nbsp;&nbsp; &nbsp;directory "etc").&nbsp;</div><div>&nbsp;&nbsp;- some bug fixes and improvements.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>See the Camlp5 documentation and the file CHANGES.&nbsp;</div><div><br class="webkit-block-placeholder"></div><div>Download the sources and the documentation at:&nbsp;</div><div>&nbsp;&nbsp; &lt;<a href="http://pauillac.inria.fr/~ddr/camlp5/">http://pauillac.inria.fr/~ddr/camlp5/</a>&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div>========================================================================</div><div>Using folding to read the cwn in vim 6+</div><div>------------------------------------------------------------------------</div><div>Here is a quick trick to help you read this CWN if you are viewing it using</div><div>vim (version 6 or greater).</div><div><br class="webkit-block-placeholder"></div><div>:set foldmethod=expr</div><div>:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'&lt;1':1</div><div>zM</div><div>If you know of a better way, please let me know.</div><div><br class="webkit-block-placeholder"></div><div>========================================================================</div><div>Old cwn</div><div>------------------------------------------------------------------------</div><div><br class="webkit-block-placeholder"></div><div>If you happen to miss a CWN, you can send me a message</div><div>(<a href="mailto:alan.schmitt@polytechnique.org">alan.schmitt@polytechnique.org</a>) and I'll mail it to you, or go take a look at</div><div>the archive (&lt;<a href="http://alan.petitepomme.net/cwn/">http://alan.petitepomme.net/cwn/</a>&gt;) or the RSS feed of the</div><div>archives (&lt;<a href="http://alan.petitepomme.net/cwn/cwn.rss">http://alan.petitepomme.net/cwn/cwn.rss</a>&gt;). If you also wish</div><div>to receive it every week by mail, you may subscribe online at</div><div>&lt;<a href="http://lists.idyll.org/listinfo/caml-news-weekly/">http://lists.idyll.org/listinfo/caml-news-weekly/</a>&gt; .</div><div><br class="webkit-block-placeholder"></div><div>========================================================================</div><div><br class="webkit-block-placeholder"></div><div><br></div><div class="AppleMailSignature" id="E12A09DE-ADCF-40D6-B7D4-306ED5CADD30"><div>--&nbsp;</div><div>Alan Schmitt &lt;<a href="http://alan.petitepomme.net/">http://alan.petitepomme.net/</a>&gt;</div><div><br class="khtml-block-placeholder"></div><div>The hacker: someone who figured things out and made something cool happen.</div><div>&nbsp;.O.</div><div>&nbsp;..O</div><div>&nbsp;OOO</div><br class="Apple-interchange-newline"> </div><br></body></html>