Commits

camlspotter  committed b5a2bb5

moved some docs

  • Participants
  • Parent commits 6113374

Comments (0)

Files changed (4)

File js_of_ocaml.rst

+=========================================
+ウェブブラウザで関数型言語を使う: js_of_ocaml
+=========================================
+
+js_of_ocaml が熱い。 Google の Dart とか、そんな場合じゃない!!
+
+OCaml で書かれたプログラムがなぜか JavaScript に変換され、それがブラウザで動く。
+JS で型がついていないオブジェクトでも何となく型をつけて OCaml 側で型安全性にブラウザで動くプログラムを書ける。生産力向上のチャンス!
+
+え?よくわからない? http://ocsigen.org/js_of_ocaml/manual/ の demo を試してご覧なさい。これが全部 OCaml で書かれている…!
+
+レシピと下準備
+==============
+
+- ocaml http://ocaml.inria.fr/
+    なきゃぁ話しにならんわな
+ 
+- findlib http://projects.camlcity.org/projects/findlib.html
+    真面目に OCaml やるなら入れてるよな!
+    
+- lwt http://www.ocsigen.org/lwt/
+    Light Weight Thread ライブラリ。 協調スレッドですからロックとかいりません。 Monadic に書きます。 Jane Street の Async も同じようなもの。片方わかればもう片方も普通に書ける。
+
+- js_of_ocaml http://ocsigen.org/js_of_ocaml/
+    肝心要の js_of_ocaml
+
+これを上から下に順番にインストール。 
+Linux なら特に問題ないはず。問題ある?それは残念ですね…
+
+動いてる?
+-----------------
+
+js_of_ocaml の examples ディレクトリで make したらブラウザで index.html にアクセス。いくつかデモがあるから動かしてみよう。
+動くはず。動かない?それは…
+
+どうやって使う?
+=================
+
+じゃあ早速 js_of_ocaml で何か作ってみよう! と言いたいところだが、まずは例題を自分の環境でコンパイルしてみるところから。
+examples ディレクトリにある例題の Makefile はソースをビルドした環境を仮定しているので、それを単にコピーするわけにはいかない。
+examples/cubes を自分の作業用ディレクトリにコピーして、次のコマンドを実行してみよう::
+
+    # camlp4o を利用した js_of_ocaml の文法拡張を使い、 lwt ライブラリを使用して cubes.ml をコンパイル
+    ocamlfind ocamlc -syntax camlp4o -package lwt,js_of_ocaml.syntax -g -c cubes.ml
+
+    # lwt と js_of_ocaml ライブラリを使って、 cubes.cmo とライブラリを cubes.byte にリンク。
+    ocamlfind ocamlc -package lwt,js_of_ocaml -linkpkg -o cubes.byte cubes.cmo
+
+    # cubes.byte を js_of_ocaml コンパイラを使用して cubes.js ファイルに変換
+    js_of_ocaml cubes.byte 
+
+上手くいけば cubes.js ファイルが出来上がっている。 
+index.html をブラウザで開けばなんか妙なデモが始まるはず。始まらない?そ…
+
+この 3つのビルドステップは Makefile に書いておくといい。私は OMake を使っているが極まりすぎているので公開してもあまり意味がないだろう。
+まあ、遊ぶだけなら shell スクリプトでも書いておけばいいはず。Shell スクリプトが書けない?…
+
+じゃあ、何か作ってみよう!
+============================
+
+例として既存の javascript を使用した例題を js_of_ocaml に少しづつ以降していくことにしよう。 
+Google chart とか、うまくいくと便利そうだから、これにしようっと。
+
+まず http://code.google.com/intl/ja/apis/chart/interactive/docs/quick_start.html の例をコピーしてブラウザで動くかどうか確認::
+
+    <html>
+      <head>
+        <!--Load the AJAX API-->
+        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+        <script type="text/javascript">
+        
+          // Load the Visualization API and the piechart package.
+          google.load('visualization', '1.0', {'packages':['corechart']});
+          
+          // Set a callback to run when the Google Visualization API is loaded.
+          google.setOnLoadCallback(drawChart);
+          
+          // Callback that creates and populates a data table, 
+          // instantiates the pie chart, passes in the data and
+          // draws it.
+          function drawChart() {
+    
+          // Create the data table.
+          var data = new google.visualization.DataTable();
+          data.addColumn('string', 'Topping');
+          data.addColumn('number', 'Slices');
+          data.addRows([
+            ['Mushrooms', 3],
+            ['Onions', 1],
+            ['Olives', 1], 
+            ['Zucchini', 1],
+            ['Pepperoni', 2]
+          ]);
+    
+          // Set chart options
+          var options = {'title':'How Much Pizza I Ate Last Night',
+                         'width':400,
+                         'height':300};
+    
+          // Instantiate and draw our chart, passing in some options.
+          var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
+          chart.draw(data, options);
+        }
+        </script>
+      </head>
+    
+      <body>
+        <!--Div that will hold the pie chart-->
+        <div id="chart_div"></div>
+      </body>
+    </html>
+
+動くよね? 
+
+js_of_ocaml 第一歩
+=======================
+
+じゃあ、この2つ目の script タグの部分を js_of_ocaml に移していこう! まず、この部分を完全にカットして、 chart.js を読み込むようにする::
+
+    <html>
+      <head>
+        <!--Load the AJAX API-->
+        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+        <script type="text/javascript" src="chart.js"></script>
+      <body>
+        <!--Div that will hold the pie chart-->
+        <div id="chart_div"></div>
+      </body>
+    </html>
+
+で、この chart.js の部分を js_of_ocaml を使って chart.ml で記述していきましょう。どうするか?まずは超簡単に::
+
+    open Js
+    
+    let _ = Unsafe.eval_string "
+            
+                  // Load the Visualization API and the piechart package.
+                  google.load('visualization', '1.0', {'packages':['corechart']});
+                  
+                  // Set a callback to run when the Google Visualization API is loaded.
+                  google.setOnLoadCallback(drawChart);
+                  
+                  // Callback that creates and populates a data table, 
+                  // instantiates the pie chart, passes in the data and
+                  // draws it.
+                  function drawChart() {
+            
+                  // Create the data table.
+                  var data = new google.visualization.DataTable();
+                  data.addColumn('string', 'Topping');
+                  data.addColumn('number', 'Slices');
+                  data.addRows([
+                    ['Mushrooms', 3],
+                    ['Onions', 1],
+                    ['Olives', 1], 
+                    ['Zucchini', 1],
+                    ['Pepperoni', 2]
+                  ]);
+            
+                  // Set chart options
+                  var options = {'title':'How Much Pizza I Ate Last Night',
+                                 'width':400,
+                                 'height':300};
+            
+                  // Instantiate and draw our chart, passing in some options.
+                  var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
+                  chart.draw(data, options);
+                }
+    "
+
+あれ?ほとんど元の JavaScript ではないか。そう。とりあえず、 Js.Unsafe.eval_string という文字列をそのまま JS として評価する関数があるので、それを使ってみたわけだ。これで、::
+
+    ocamlfind ocamlc -syntax camlp4o -package lwt,js_of_ocaml.syntax -g -c chart.ml
+    ocamlfind ocamlc -package lwt,js_of_ocaml -linkpkg -o chart.byte chart.cmo
+    js_of_ocaml chart.byte 
+
+を実行する、そんで index.html を読み込む。 Pie chart が出るはず。出ない?…
+
+そら eval するだけだから出るのは当たり前だろう、バカにしているのか?と言ってはいけない。 js_of_ocaml、まず第一歩はこういう eval から始めるのがいいみたい。とりあえずワケわからなくなったら Js.Unsafe.eval_string で様子を見てみる、これ大切。
+
+関数を作って JS に渡してみよう!
+====================================
+
+もうすこし複雑なことをしてみよう。 JS の drawChart 関数を OCaml に移す::
+
+    open Js
+            
+    let drawChart () = Unsafe.eval_string "
+                  // Create the data table.
+                  var data = new google.visualization.DataTable();
+                  data.addColumn('string', 'Topping');
+                  data.addColumn('number', 'Slices');
+                  data.addRows([
+                    ['Mushrooms', 3],
+                    ['Onions', 1],
+                    ['Olives', 1], 
+                    ['Zucchini', 1],
+                    ['Pepperoni', 2]
+                  ]);
+            
+                  // Set chart options
+                  var options = {'title':'How Much Pizza I Ate Last Night',
+                                 'width':400,
+                                 'height':300};
+            
+                  // Instantiate and draw our chart, passing in some options.
+                  var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
+                  chart.draw(data, options);
+               "
+      
+    let _ = Unsafe.eval_string "
+                  // Load the Visualization API and the piechart package.
+                  google.load('visualization', '1.0', {'packages':['corechart']});
+            ";
+            Unsafe.meth_call (Unsafe.variable "google") "setOnLoadCallback" [| Unsafe.inject drawChart |]
+
+JS の drawChart 関数をそのまま OCaml の drawChart 関数に写しただけ。相変わらず、中身は eval_string。
+この OCaml の drawChart 関数は js_of_ocaml コンパイラでコンパイルしても drawChart という名前にはならない。
+だから、drawChart を使う、元の JS の google.setOnLoadCallback(drawChart); メソッド呼び出しはそのまま eval_string することはできない。
+Unsafe.meth_call を使う::
+
+            Unsafe.meth_call (Unsafe.variable "google") "setOnLoadCallback" [| Unsafe.inject drawChart |]
+
+- Unsafe.meth_call は JS のメソッド呼び出し。第一引数が JS のオブジェクト、第二がメソッド名、第三が引数配列。
+- オブジェクトは JS で google と言う変数に束縛されているので Unsafe.variable "google" として、その変数を使う
+- メソッド名は文字列なのでそのまま
+- 引数はひとつ、 drawChart 関数を渡すのだけど、そのままでは型が合わないので Unsafe.inject を使う
+
+これで動くはず。動かない?それは残念ですね… と言いたいところだが、
+
+動かなかったら
+--------------------
+
+js_of_ocaml で何か上手く行かなかったら、こうするといい
+
+  - アウトプットの js ファイルを良く見る。なんとなく読める。 (というか OCaml のバイトコードからそれなりに人間が読める JS コードを吐ける事に驚く。バイトコードがあればリバースエンジニアリングできるということだからだ! (10年ほど前にはそんな事は出来っこないから、商用コードでもバイトコードで配布すれば安心!というのが常識だった))
+  - ブラウザのエラーコンソールを良く見る。なんとなくわかる。
+
+とにかく、急いで全部 OCaml にしない事。一歩々々確かめて、知見はメモするのがいい。この Chart 移植作業中にもいくつかポイントがあった。瑣末だから敢えて書かないけど。
+
+まあ、 Unsafe ですから!!
+--------------------------
+
+Unsafe モジュールの関数は超低レベル。とにかく JS と話をするためだけに作られている。型を合わせていない。だから簡単な間違いでも型検査で見つけることができない。そこんとこ宜しく。
+
+文字列と JS literal object
+===============================
+
+とりあえず drawChart の eval_string は置いておいて、下の数行をもうちょっと OCaml っぽくしていこう::
+
+    let google = Unsafe.variable "google"
+    let _ = 
+        (* Load the Visualization API and the piechart package. *)
+        Unsafe.meth_call google "load" [| Unsafe.inject (Js.string "visualization"); 
+                                          Unsafe.inject (Js.string "1.0");
+                                          Unsafe.inject (Unsafe.variable "{'packages':['corechart']}") |];
+        Unsafe.meth_call google "setOnLoadCallback" [| Unsafe.inject drawChart |]
+
+ここでの改変ポイントは
+
+- OCaml 文字列は Js.string 関数で JS の文字列オブジェクトに変更。 Unsafe.meth_call に不安全に突っ込むために Unsafe.inject を使用。
+- JS literal object {'packages':['corechart']} は今の所良い記述法が無いので Unsafe.variable "文字列" で代用
+
+JS literal object については実は {: packages = [ "corechart" ] :} みたいな書き方ができるようなパッチがつい最近出たみたいだけど、 stable 版には入っていないみたい。とりあえず変数として文字列をぶち込めば、気持ち悪いけど動く。 取り入れられるまで、待ちましょう。
+
+とりあえず、ここんとこ改変して動かしてみよう。
+
+Class type で JS のオブジェクトをエンコード
+=========================================
+
+さて、ここから面白くなってくる。 JS に型もクソもないが、JS のオブジェクトの型を何となく OCaml の class type として記述することで、 JS のオブジェクトのインターフェースを OCaml内のクラスとして型安全に使用することが出来る!。 今まで例を引き続き使って、 google オブジェクトのクラス型を考えよう::
+
+    class type g = object
+      method load : js_string t -> js_string t -> 'a t -> unit meth
+      method setOnLoadCallback : (unit -> unit) -> unit meth
+    end
+    
+とりあえず、 google のメソッドは load と setOnLoadCallback を使っている。このメソッドを持つ class type g を定義している。
+
+メソッドの OCaml でのあるべき型を何となく想像しよう。例えば、 load は string を二つ、その次によくわからない JS object を受け取り、返り値は unit でいいだろう。つまり、 string -> string -> 'a -> unit だ。 'a はとりあえず、よくわかんないから型変数にしておいた。
+
+class type g の load メソッドが、この型を持つと宣言するのだが、そのまま string -> string -> 'a -> unit と書くわけではなく、ちょっとした変換が必要だ。ここんとこちょい面倒で自動で出来そうなものだが、まあ、ルールは簡単だから手でもできる
+
+- JS のオブジェクトの型は 'a Js.t。 'a は phantom type でオブジェクトの中身の型。例えば JS の文字列オブジェクトの型は js_string Js.t になる。 ここでは open Js しているので js_string t になっている。
+
+- リターンの型は別の phantom type 'a meth で修飾する。ここでは、なんとなく想像したリターン型は unit だから unit meth。
+
+- わかんない型もとりあえず 'a t として、何か JS のオブジェクトが来るってことにする。もちろん型安全性は失われるが、どうせ JS だから。
+
+- 引数の型が関数の場合、オブジェクトではないので t で修飾する必要は無い。
+
+というわけで、 method load の型は js_string t -> js_string t -> 'a t -> unit meth になる。
+
+setOnLoadCallback も同様。このメソッドはコールバック関数をもらってそれを登録するから、 OCaml 的には (unit -> unit) -> unit の型を持つ。これを上のルールに従って変換する。 (unit -> unit) -> unit meth。
+
+さて、インターフェースを OCaml の型で宣言できた。 変数 google にはこのインターフェースを持つオブジェクトが入っているはずだから、それを明示しよう::
+
+    let google : g t = Unsafe.variable "google"
+
+google は JS object なので g t って型になる。 t を忘れないように。
+
+js_of_ocaml では c JS.t という型、つまり c というインターフェースを持つ JS object に対し、特殊な糖衣構文を使って型安全にメソッド呼び出しができる::
+
+    let _ = 
+        (* Load the Visualization API and the piechart package. *)
+        google##load (Js.string "visualization",
+                      Js.string "1.0",
+                      Unsafe.variable "{'packages':['corechart']}");
+        google##setOnLoadCallback (drawChart)
+    
+ここでのポイントは
+
+- OCaml の普通のメソッド呼出 # と違って、 ## を使う
+- JS のメソッドは uncurry form で呼び出す。 class type での宣言は curried であるのだが。
+- 一引数、ゼロ引数であっても JS メソッド名の後には () が必須。 google##setOnLoadCallback drawChart とは書けない
+
+当然ながら今度は Unsafe を多用していた時と違って、かなり型安全になっている。例えば setOnLoadCallback に違う型の関数を適用することはできない。
+
+js_of_ocaml ではこんな風に、既存の JS クラスに適当な型を与えて OCaml 側で型安全性を使ったプログラミングが出来る。もし完全に型をエンコードできなければ型変数を使ってとりあえず、その部分だけの型安全性を諦めることも出来る。非常に柔軟かつ簡単に複雑な JS 資産を OCaml 側で利用できる仕組みを持っていると言えるだろう。
+
+例によって、最後の部分をこの class type 宣言、 google の定義、 google の使用のコード片に書き換えて動作を確認しよう。
+
+プロパティと new
+============================================
+
+さて、これで元の JS の最後の部分は OCaml に移すことが出来た。 (JS literal object が甘いが、今の所エレガントにはできないのだからまあ、よしとする) こんどは drawChart の eval_string の部分を移植していこう。
+
+ここでの問題は、 new google.visualization.PieChart() に見られる、
+
+- google.visualization というプロパティアクセス
+- new
+
+の二つ。
+
+プロパティも class type にエンコード
+-------------------------------------------- 
+
+JS object のプロパティも class type にエンコードすることで OCaml 側でアクセスすることが可能だ。 visualization というプロパティを google のクラス型 g に足してみよう::
+
+    class type g = object
+      method load : js_string t -> js_string t -> 'a t -> unit meth
+      method setOnLoadCallback : (unit -> unit) -> unit meth
+      method visualization : 'a t readonly_prop
+    end
+    
+とりあえず、 google.visualization の型は何かわからないので 'a t という型にしておいた。 google.visualization はメソッドではなく、プロパティなので、 meth の代わりに readonly_prop という phantom type を使う。こう記述しておくと、 google##visualization という OCaml コードで JS の google.visualization にアクセスできる。
+
+もし JS object o のプロパティ p が変更可能な場合、 readonly_prop の代わりに普通の prop を使う。その場合は、 o##p でプロパティを読み出すだけでなく、 o##p <- e でプロパティの上書きが可能だ。
+
+クラスコンストラクタ は constr でエンコード
+------------------------------------------
+
+上では visualization はとりあえず 'a t という型だと想定したが、 new google.visualization.PieChart(...) という使われ方をしているから、
+
+- PieChart にアクセスできる
+- PieChart は HTML の要素を取って new できる
+
+事が判る。今度はこの visualization を OCaml の class type にエンコードしよう::
+
+    class type v = object
+      method _PieChart : (Dom_html.element t -> 'a t) constr readonly_prop
+    end
+
+- PieChart は大文字から始まる。 OCaml では大文字から始まるメソッドは定義できないので _ を前に付ける。 _PieChart。
+- PieChart は read only prop
+- PieChart はオブジェクトではなく新しいオブジェクトを new できるコンストラクタ。なので constr phantom type でそれを明示。
+- new google.visualization.PieChart(e) は HTML の element を取る。その型は Dom_html.element t。 そして作られるオブジェクトは…例によって良く判らないので 'a t にしておく
+
+v を用意したので、 google.visualizaiton の型は v t と書くことが出来る。 class type g を修正::
+
+    class type g = object
+      method load : js_string t -> js_string t -> 'a t -> unit meth
+      method setOnLoadCallback : (unit -> unit) -> unit meth
+      method visualization : v t readonly_prop
+    end
+
+これで、準備完了。 new google.visualization.PieChart(e) は OCaml では次のように書くことが出来る::
+
+    jsnew (google##visualization##_PieChart) (e)
+
+- PieChart へのアクセスは ## を使う
+- JS object の new は OCaml の new ではなく、 jsnew を使う
+- jsnew の引数にはカッコが必須。 (constructor に ## が入っている場合もカッコがいる
+
+どんどん変えていこう
+=================================
+
+さて、ここらで一度動くコードが提示できると嬉しいのだけど…残念ながら、一気にやっていかないといけない。 (eval_string 内で変数にバインドしてもその後使えないので…)
+
+- new google.visualization.PieChart(...) の結果は 'a t では寂しい。結果の chart は draw というメソッドを持っているので、 chart という class type を定義。 draw メソッドを宣言
+
+- PieChart と同様に、 DataTable を constr readonly_prop として class type v に定義
+
+- new google.visualization.DataTable() の結果は addColumn と addRows というメソッドを持っているので、それも class type に定義
+
+これを全部やったのが次::
+
+    open Js
+            
+    class type dataTable = object
+      method addColumn : js_string t -> js_string t-> unit meth
+      method addRows : 'a t -> unit meth
+    end
+    
+    class type chart = object
+      method draw : dataTable t -> 'a t -> unit meth
+    end
+    
+    class type v = object
+      method _DataTable : dataTable t constr readonly_prop
+      method _PieChart : (Dom_html.element t -> chart t) constr readonly_prop
+    end
+    
+    class type g = object
+      method load : js_string t -> js_string t -> 'a t -> unit meth
+      method setOnLoadCallback : (unit -> unit) -> unit meth
+      method visualization : v t readonly_prop
+    end
+      
+    let google : g t = Unsafe.variable "google"
+    
+    let drawChart () = 
+      let data = jsnew (google##visualization##_DataTable) () in
+      data##addColumn (Js.string "string", Js.string "Topping");
+      data##addColumn (Js.string "number", Js.string "Slices");
+      data##addRows ( Unsafe.eval_string "[
+                    ['Mushrooms', 3],
+                    ['Onions', 1],
+                    ['Olives', 1], 
+                    ['Zucchini', 1],
+                    ['Pepperoni', 2]
+                  ]" );
+      let options = Unsafe.variable "{'title':'How Much Pizza I Ate Last Night',
+                                     'width':400,
+                                     'height':300}" 
+      in
+      let div = Unsafe.eval_string "document.getElementById('chart_div')" in
+      let chart = jsnew (google##visualization##_PieChart) (div) in
+      chart##draw(data, options)
+    
+    let _ = 
+        (* Load the Visualization API and the piechart package. *)
+        google##load (Js.string "visualization",
+                      Js.string "1.0",
+                      Unsafe.variable "{'packages':['corechart']}");
+        google##setOnLoadCallback (drawChart)
+
+注意点は…
+
+- addRows の第一引数と draw の第二引数の型は、まあ、とりあえず放っとく。 Unsafe.eval_string したものを渡すので
+- options は例によって JS literal object なので Unsafe.variable "文字列" で代用
+
+まだちょっと Unsafe な部分はあるが、大部分が OCaml の型安全な世界に移ってきた。
+
+仕上げ
+=================================
+
+残りの Unsafe や取りあえずの method 型宣言内の型変数を減らそう。 (JS literal object は置く。)
+
+- addRows の第一引数の型は JS object の配列の配列なので、 'a t js_array t js_array t。 ('a の部分は…難しい)
+- OCaml で記述したピザデータから JS 文字列の配列の配列を作るためのコード
+- HTML の chart_div という id を持ったエレメントを探すため Dom_html モジュールを使用
+
+最終的にはこんなコードになる::
+
+    open Js
+            
+    class type dataTable = object
+      method addColumn : js_string t -> js_string t-> unit meth
+      method addRows : 'a t js_array t js_array t -> unit meth (* 引数の型を明確化 *)
+    end
+    
+    class type chart = object
+      method draw : dataTable t -> 'a t -> unit meth
+    end
+    
+    class type v = object
+      method _DataTable : dataTable t constr readonly_prop
+      method _PieChart : (Dom_html.element t -> chart t) constr readonly_prop
+    end
+    
+    class type g = object
+      method load : js_string t -> js_string t -> 'a t -> unit meth
+      method setOnLoadCallback : (unit -> unit) -> unit meth
+      method visualization : v t readonly_prop
+    end
+      
+    let google : g t = Unsafe.variable "google"
+    
+    let drawChart () = 
+      let data = jsnew (google##visualization##_DataTable) () in
+      data##addColumn (Js.string "string", Js.string "Topping");
+      data##addColumn (Js.string "number", Js.string "Slices");
+      (* 食べたピザデータを OCaml の (string * int) list で表現 *)
+      let rows = [ ("Mushrooms", 3); 
+                   ("Onions", 1);
+                   ("Olives", 1); 
+                   ("Zucchini", 1);
+                   ("Pepperoni", 2) ]
+      in
+      (* JS のオブジェクトへ変換 *)
+      let rowsJS = 
+        Js.array (Array.of_list (List.map (fun (name,q) -> 
+          Js.array [| Js.string name; 
+                    (* No phantom for top type? *)
+                      Obj.magic q |])  rows))
+      in
+      data##addRows(rowsJS);
+      let options = Unsafe.variable "{'title':'How Much Pizza I Ate Last Night',
+                                     'width':400,
+                                     'height':300}" 
+      in
+      (* Dom アクセスで chart_div という名前のエレメントを取得。無ければ、残念です… *)
+      let div = match Opt.to_option (Dom_html.window##document##getElementById (Js.string "chart_div")) with
+        | None -> assert false
+        | Some div -> div
+      in
+      let chart = jsnew (google##visualization##_PieChart) (div) in
+      chart##draw(data, options)
+    
+    let _ = 
+        (* Load the Visualization API and the piechart package. *)
+        google##load (Js.string "visualization",
+                      Js.string "1.0",
+                      Unsafe.variable "{'packages':['corechart']}");
+        google##setOnLoadCallback (drawChart)
+
+残った Unsafe は、ごくわずか。
+
+- google オブジェクトは g t という型を持つよー。これはしょうがない
+- JS literal object の部分。これは多分すぐにエレガントに書けるようになる。 Wktk して待て!
+
+まとめ
+=================================
+
+js_of_ocaml を導入すれば、既存の JS 資産を利用した HTML ページを、簡単な eval_string を使ったものから始めて、最終的にほとんどのコードを OCaml に移植する事が出来る。これを Google の Chart API を使った例を通して見てみた。実際カンタン!
+
+JS のオブジェクトのインターフェースは、いくつかのルールを覚えれば、簡単に OCaml の class type として宣言し、 OCaml 内で静的型安全に使用することができる。とはいえ、ガッチムチに硬いわけでもなく、完全な静的型安全性が得にくい場合は、その部分だけの安全性を捨て、 JS 側の動的型検査にまかせることができる。すごく柔軟だ!!
+

File monad_functor.rst

+====================================================================
+Monad にしちゃう functor を通して今時の OCaml モジュールプログラミングを俯瞰
+====================================================================
+
+これは私用の覚え書き。 
+OCaml や ML のモジュールシステム、 value polymorphism、さらには relaxed value polymorphism 
+を知っている人にも役に立つかもしれない。
+
+OCaml 3.12.0 位から以降限定の技だ。
+
+既存モジュールの型 'a t が実はモナドだったので、モナドのインターフェースを加えたい、という時が、ままある。
+例えば、 'a Lazy.t は、モナドになる。でもモナドの bind とか return が定義されていない。
+モナドの便利な関数群もない。それを functor で拡張していこう。
+ここで言う functor とは ML のそれである。モジュールを受取りモジュールを返す関数。モナドのそれと勘違いしないこと。
+
+最低限の Monadic interface を作る
+=================================
+
+まずモナドとして最低限提供されてなきゃいけない関数群をモジュールとして見て、その型を考える::
+
+  module type S = sig
+    type 'a t
+    val return : 'a -> 'a t
+    val bind : 'a t -> ('a -> 'b t) -> 'b t
+  end
+
+この場合は、 return と bind が最低限必要ってことにした。
+
+'a Lazy.t にモナド風味を付け加えるには、::
+
+  module MLazy : S (* 便宜的に Lazy.t の実装を隠してある *) = struct
+    type 'a t = 'a Lazy.t
+    let return v = Lazy.lazy_from_val v
+    let bind x f = f (Lazy.force x)
+  end
+
+これでいい。あ、でもこれじゃ MLazy に Lazy の元々の関数が入ってないじゃないか! まあそれは後で考える。
+MLazy の型を明示的に書くことで、 MLazy.t が Lazy.t と同じことを隠している。
+本来、これを書く必要は無いのだが、次の説明に必要なので。
+
+Covariant にしよう
+=================================
+
+ちょっとここでひと工夫。 OCaml は (relaxed) value polymorphism があるので、関数適用時の多相性に制限がある::
+
+  let x = MLazy.return []
+
+これは多相値にならない。 '_a list MLazy.t である。
+Monadic なプログラミングでは return や bind を多用するので、これは困る。
+そこで、 S.t の型パラメタを covariant だということにして、この問題を回避できる。::
+
+  module type S = sig
+    type +'a t (* Covariant ですぞ *)
+    val return : 'a -> 'a t
+    val bind : 'a t -> ('a -> 'b t) -> 'b t
+  end
+
+  module MLazy : S (* 便宜的に Lazy.t の実装を隠してある *) = struct
+    type 'a t = 'a Lazy.t
+    let return v = Lazy.lazy_from_val v
+    let bind x f = f (Lazy.force x)
+  end
+
+こうしておくと、 relaxed value polymorphism のお蔭で、 return や bind 適用時にも多相性が失われることがない!::
+
+  let x = MLazy.return []
+
+はちゃんと 'a list MLazy.t になる。
+
+もちろんモジュール型 S は元の S より条件が厳しくなるので、今から作る functor の取りうるモジュールの幅が狭まるが、
+今のところ covariant 以外の 'a t をモナドにしようと思ったことが無いので、まあこれでよかろう。
+(もし convariant でない 'a t をモナドにしようとすれば別の S' を定義して以下の functor Make もまた別の Make'
+を定義することになる。もちろんその Make'(A) の関数群は relaxed value polymorphism の恩恵は受けることはできないが。)
+
+MLazy の型制限も必要ないから外しておこう::
+
+  module MLazy = struct
+    type 'a t = 'a Lazy.t
+    let return v = Lazy.lazy_from_val v
+    let bind x f = f (Lazy.force x)
+  end
+
+強化 functor, Make を作ろう
+==================================
+
+S の型を持つ基本モジュールを作るのはプログラマの仕事。そこからいろいろ自動的にモナディックな関数群を創りだす
+functor、 Make を定義しよう。まず、強化されたモジュール型から::
+
+  module type T = sig
+    include S
+
+    val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
+    val map : ('a -> 'b) -> 'a t -> 'b t
+    val sequence : 'a t list -> 'a list t
+  end
+
+T は S に関数を足したもので、まあ、二つしか足してないが…まあ好きなだけ足せばいい。
+Make は S の型を持つ基本モジュール A をもらって型 T に強まったモジュールを返す。
+実装::
+
+  module Make (A : S) : T = struct
+    include A
+
+    let (>>=) = bind
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+(>>=) と sequence の定義はごく普通。 ふむ、出来た。使ってみる::
+
+  module XLazy = Make(MLazy)
+
+  let v = [ MLazy.return []; XLazy.return [] ] (* 型エラー *)
+
+あれ? 強化前のモナドと強化後のモナド、同じはずなのに、一緒の型を持てないからリストに入れられない…
+型システムが MLazy.t と XLazy.t を別の型だと思っているのだ。
+
+なぜか? module Make (A : S) : T = ... の所で明示的に結果のモジュールの型を T と提示しているが
+T.t が A.t と同じであると宣言するのを忘れている! この情報を教えてやらなければいけない::
+
+  module Make (A : S) : T with type 'a t = 'a A.t (* 型の同値を足した *) = struct
+    include A
+
+    let (>>=) = bind
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+なんと面倒な! 実は、この返り型を書かなければ、型システムがよろしくやってくれる! ::
+
+  module Make (A : S) = struct
+    include A
+
+    let (>>=) = bind
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+この様に、モジュールを使ったプログラミングではプログラマが情報を必要以上に減らしたモジュール型を書いてしまって
+型の同値性が知らず知らずに失われてしまう、ということが、ままある。モジュールを使わない所では型推論の恩恵に
+慣れきっている我々には難しいところだ…
+
+基本的には functor の引数の型など必要なモジュール型以外は、とりあえず、書かない、のが吉なようだ。
+ただし、ライブラリとして functor の返りモジュールの型情報は合ったほうがよいし(特に .mli)、
+そうなると、上の T やT with 'a t = 'a A.t の記法も避けられない。
+ここんとこの勘所を身につけるには修行が必要だ。
+
+Binary operator のための特殊名前空間を作る
+================================================
+
+さて、 module XLazy = Make(MLazy) で、強化モジュールが出来た。
+XLazy.(>>=) をバリバリ使いたいのだが、それには XLazy.(>>=) と一々書くのは面倒だから、
+open XLazy を唱えてちゃんと二項演算子として使えるようにしてやろう!
+と言いたいところだが、ちょっと待て。 open XLazy すると (>>=) どころか map や sequence も
+アクセス可能になる。 map は特に一般的なイディオムだから名前空間を開きすぎだ。
+やはり map はあくまでも map ではなく XLazy.map としてアクセスしたい。
+そのために open 用のモジュール、 XLazy.Open を定義しよう::
+
+  module Make (A : S) = struct
+    include A
+
+    module Open = struct
+      let (>>=) = bind
+    end
+
+    include Open
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+こうすると、 module XLazy = Make(MLazy) とした場合、 (>>=) は XLazy.(>>=) としても、
+XLazy.Open.(>>=) としてもアクセスできる。 open XLazy.Open を唱えれば Open の中で定義されている
+(>>=) だけがグローバルな名前空間に踊りでてくるという寸法だ。
+
+まあ、型クラスがあればこんな事気にしなくて良いのだが…無いものはしょうがない。
+
+拡張前の元のモジュールと統合: with type 'a t := ... を使う!
+=========================================================
+
+Lazy モジュールには、型 'a t の他にいろいろな関数が定義されているが、 MLazy そして強化された XLazy
+にもそれらの関数は入っていない。 これは、 XLazy を MLazy ではなく、 Lazy に return と bind を加えたものから
+作っても同じ事だ。::
+
+  module MLazy' = struct
+    include Lazy
+    val return : 'a -> 'a t
+    val bind : 'a t -> ('a -> 'b t) -> 'b t
+  end
+
+  module XLazy' = Make(MLazy')
+
+XLazy' は Lazy そして MLazy' に存在する関数群が継承されていない。残念だが functor の引数は閉じた型しか
+取れないので、いくら functor 引数にリッチなモジュールを与えても、 functor 内部では引数モジュールの型として
+宣言したプアーな型しか持っていないのだ。他は、忘れ去られてしまう。
+
+まあ、 Lazy と XLazy を使い分ければ良いのだが…できればこの二つの機能を合わせ持つ 俺Lazy が欲しいところだ。
+これならどうだ?::
+
+  module Lazy = struct
+    include Lazy
+    include XLazy (* うまくいかない! *)
+  end
+
+残念だが上手くいかない。 Lazy も XLazy も 'a t を定義している。同じ名前の型定義が二つ以上モジュールには存在できないのだ。
+しかしこれは妙な話だ。 'a XLazy.t = 'a Lazy.t という同値関係を型システムは知っているのだから、問題はないはずなのに。
+'a XLazy.t が 'a Lazy.t と同じであることを宣言してみよう::
+
+  module Lazy = struct
+    include Lazy
+    include (XLazy : T with 'a type t = 'a Lazy.t) (* うまくいかない! *)
+  end
+
+これも上手くいかない。無理なのか、と思いきや、こんなのが使える::
+
+  module Lazy = struct
+    include Lazy
+    include (XLazy : T with type 'a t := 'a Lazy.t) (* たった一文字加えただけなのに! *)
+  end
+
+一体何が? これは次の例を見れば、わかる、かもしれない::
+
+  module type S = sig
+    type t
+    type s = Foo of t
+  end
+
+  module type S' = S with type t = int
+
+  module type S'' = S with type t := int
+
+上のソースを ocamlc -c -i でコンパイルすると次のような解釈になっているのがわかる::
+
+  module type S = sig type t type s = Foo of t end
+
+  module type S' = sig type t = int type s = Foo of t end (* t = int という同値関係が導入されている *)
+
+  module type S'' = sig type s = Foo of int end (* t が無くなって int に置き換わっている! *)
+
+with type ... = と with type ... := の違いがわかるだろうか。 := では「代入」された元の型は結果のモジュール型から
+消え去り、右辺の型に置き換わってしまっている。これを使って、 T with type 'a t := 'a Lazy.t と書けば、
+XLazy のモジュール型を型 t の定義の無いものへと制限することが出来る。そして、 Lazy と (XLazy  : T with type 'a t := 'a Lazy.t)
+には危険な t の定義対はもはや存在しない!
+
+この := を Make に移してみよう::
+
+  module Make (A : S) : T with type 'a t := 'a A.t (* t を置換する! *) = struct
+    include A
+
+    module Open = struct
+      let (>>=) = bind
+    end
+
+    include Open
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+こうすれば、 Make(Lazy) には最早 t の型定義は存在しない。だから、::
+
+  module MLazy = struct
+    type 'a t = 'a Lazy.t
+    let return v = Lazy.lazy_from_val v
+    let bind x f = f (Lazy.force x)
+  end
+
+  module XLazy = Make(MLazy)
+
+  module Lazy = struct
+    include Lazy
+    include XLazy
+  end
+
+で上手く書ける!
+
+結果を Monad モジュールにまとめよう
+====================================
+
+今までの結果を Monad モジュールにまとめよう::
+
+  (* 最低限の monadic module type *)
+  module type S = sig
+    type +'a t (* covariant *)
+    val return : 'a -> 'a t
+    val bind : 'a t -> ('a -> 'b t) -> 'b t
+  end
+
+  (* 強化された monadic module type *)
+  module type T = sig
+    include S
+
+    module Open : sig
+      val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
+    end
+    val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
+    val map : ('a -> 'b) -> 'a t -> 'b t
+    val sequence : 'a t list -> 'a list t
+  end
+
+  (* 最低限から強化版を創りだす functor *)
+  module Make(A : S) : T with type 'a t := 'a A.t = struct
+    include A
+
+    module Open = struct
+      let (>>=) = bind
+    end
+
+    include Open
+
+    let map f t = bind t (fun x -> return (f x))
+
+    let rec sequence = function
+      | [] -> return []
+      | x::xs ->
+          x >>= fun x ->
+          sequence xs >>= fun xs ->
+          return (x::xs)
+  end
+
+実際に私が使っている monad.ml はこんな感じ。 https://bitbucket.org/camlspotter/spotlib/src/c97d21e10999/lib/monad.ml
+
+- より多くのモナド操作関数
+- 2 つの型パラメータのモナド用 functor (OCaml には kind inference が無い…無念!)
+
+Oreore モジュールで強化版モジュール群を管理
+=========================================================
+
+さて、これでモナドのインターフェースを持たないモジュールを
+
+- 最低限のモナディックインターフェースを与える (MLazy)
+- それを functor で強化してやる ( module XLazy = Make(MLazy) )
+- 元のモジュールと統合する ( include Lazy, include XLazy )
+
+の三ステップでモナドインターフェースを与えることができた。
+
+例えば、 oreore.ml に::
+
+  (* oreore.ml *)
+
+  ...
+
+  module Lazy = struct
+    include Lazy
+    include XLazy
+  end
+
+と書いておけば、 open Oreore と唱えれば、
+さっきまでヒヨワだったハズの Lazy がモナディックな Lazy として立ち上がってくるわけだ。
+Oreore モジュールにはこうやって自分で強化したモジュールをどんどん足していけばいい。
+
+Lazy の中で Lazy を include しているのが気持ち悪い、という人は、::
+
+  module Stdlib = struct
+    module Lazy = Lazy
+  end
+
+  module Lazy = struct
+    include Stdlib.Lazy
+    include XLazy
+  end
+  
+とでもして、明示的に include されてる Lazy はオリジナルの stdlib 由来だと判るようにすればいいだろう。
+私はそこまでしてもあまりしょうがないかな、と思っている。
+
+oreore.mli を完結に書く
+=========================================================
+
+最後に oreore.mli を書いておこう。上の例だと強化 Lazy の signature を書くことになる。
+
+一番カンタンなのは、オリジナルの Lazy からコピペする方法。でも、ダサい。というかコピペ死すべし。
+コピペでは、オリジナルの Lazy に関数が足された場合、 Oreore.Lazy の signature 方が追随できない。
+
+それより完結なのは module type of Lazy を使う方法。こんな感じだ::
+
+  (* oreore.mli *)
+  module Lazy : sig
+    include module type of Lazy
+    (* Inherits the original Lazy module *)
+
+    include Monad.T with type 'a t := 'a Lazy.t
+    (* Adding monadic interface *)
+  end
+
+これを見れば Lazy はオリジナルの Lazy と Monadic インターフェースの両方持ってるのね、とわかる。
+
+実はこんなにすっきり行くのは Lazy.t が type 'a t = 'a lazy_t というエイリアスだから。
+Variant や record 型が含まれている場合は厄介だ。::
+
+  (* oreore.mli *)
+  module Unix : sig (* 実は良くない *)
+    include module type of Unix
+    (* Inherits the original Unix module *)
+
+    val usleep : float -> unit
+    (** better sleep *)
+  end
+
+これは Unix モジュールに usleep を足してみたものの signature (良くない)。 usleep の実装は、まあ適当に interval_timer を
+使えば OCaml だけで書けるので実装は省略。
+
+実はこれが良くない。オリジナルの Unix 中の variant や record 型と強化 Unix の型が別モノと認識されるのだ。
+強化 Unix だけ使っていれば問題はないが…もし第三者のライブラリがオリジナルの Unix を使っていて、そこから得られる
+値、例えば型 open_flag の値を強化 Unix で使おうとすると…使えない。
+
+なんで?これは次の例でわかる::
+
+  $ ocaml unix.cma
+
+  # module U : module type of Unix = Unix;;
+
+  module U : sig
+    ...
+
+    type open_flag =
+        O_RDONLY
+      | O_WRONLY
+      | O_RDWR
+      | O_NONBLOCK
+      | O_APPEND
+      | O_CREAT
+      | O_TRUNC
+      | O_EXCL
+      | O_NOCTTY
+      | O_DSYNC
+      | O_SYNC
+      | O_RSYNC
+
+    ...
+  end
+
+え? open_flag ちゃんとあるじゃん? でも、これは Unix.open_flag じゃなくて U.open_flag。両者には何の関係もない!
+Unix.O_RDONLY = U.O_RDONLY は型エラーになる! これは、例えば::
+
+  module A = struct type t = Foo end 
+  module B = struct type t = Foo end 
+
+と書いたときに A.t と B.t は定義の字面は同じだけど違う型なのと同じ理由だ。(同じだったら困る!)
+この B.t が A.t と実は同じ、と言いたければその事をちゃんと示してやらねばならない::
+
+  module A = struct type t = Foo end 
+  module B = struct type t = A.t = Foo end  (* 同値関係を明示 *)
+
+これと同じ事を(U や)強化Unix に対してもしてやれば、オリジナル Unix との interoperability を実現できる::
+
+  (* oreore.mli *)
+  module Unix : sig
+    include module type of Unix with type open_flag = Unix.open_flag
+    (* Inherits the original Unix module *)
+
+    val usleep : float -> unit
+    (** better sleep *)
+  end
+   
+あー、これで完成! いや、 Unix には他にも沢山型があるのだ。それについても同値性を宣言しなければ…ならない! ::
+
+  (* oreore.mli *)
+  module Unix : sig
+    include module type of Unix 
+    with type error		= Unix.error
+    and  type process_status	= Unix.process_status
+    and  wait_flag		= Unix.wait_flag
+    and  open_flag		= Unix.open_flag
+    and  seek_command		= Unix.seek_command
+    and  file_kind		= Unix.file_kind
+    and  stats			= Unix.stats
+    and  ...
+    (* Inherits the original Unix module *)
+
+    val usleep : float -> unit
+    (** better sleep *)
+  end
+
+これは…めんどくさい!! 残念ながら今のところ、この with type の長い列がついたモノと同等の signature を
+簡単に得る記法は存在しない。
+
+この場合は、敢えて、 強化 Unix の signature を書かない、つまり、 oreore.mli を書かないのも選択の一つだ。
+.mli の無いライブラリモジュールなんて! いやしかし、 .ml は至極カンタンに書ける。ならば .mli は必要ない! ::
+
+  (* xunix.ml *)
+  let usleep sec = ...
+
+  (* xunix.mli *)
+  val usleep : float -> unit
+  (** better sleep *)
+ 
+  (* oreore.ml *)
+  module Unix = struct
+    include Unix
+    (* Inherits the original Unix module *)
+
+    include Xunix
+    (* Inherits my extended XUnix *)
+  end
+
+ここでは Unix に付け加える関数 usleep を xunix.ml に定義、そのドキュメントを xunix.mli に書いて、
+oreore.ml でそれを include している。 oreore.mli は無い。 oreore.mli が無いからドキュメントが…
+心配する必要は無い。 oreore.ml はシンプルだ。 Unix はオリジナルの Unix と強化 Xunix から出来ている。
+オリジナル Unix も Xunix もちゃんとドキュメント化された .mli が用意されているからそれを参照すればよい。
+==========================================
+OCaml のパッケージシステム OASIS を使ってみた
+==========================================
+
+*この文書は新情報が入り次第、適時更新します。*
+
+今日も OCaml ライブラリのソースをダウンロードするところから始めている皆さん、こんにちは。
+
+はっきり言って、面倒ですよね。一度ダウンロード、コンパイルに成功したら、それのソースツリーを置いておけばそれまでなんですが、
+他のマシンでコンパイルしたくなったりしますよね。
+私はブチ切れて OMake で指定 URL からダウンロードして apt-get+configure+make+install までオンデマンドでやっちゃうシステムを組みました。
+マシンが変わっても ``omake`` 一発で全部やってくれるのが気持ちいいです。 (https://bitbucket.org/camlspotter/omy/overview)
+
+それでもやっぱり、ライブラリがバージョンアップしたら、また始めからソース取ってきて確認、は変わりません。
+
+そうなるとやっぱり、 OCaml にも、 Haskell の Cabal みたいなパッケージシステムが欲しい所ですよね。
+GODI (http://godi.camlcity.org/godi/index.html) とかもあるんですが、 GODI のパッケージは GODI にしか使えない。また、良くも悪くも GODI の為のパッケージングしか提供しません。
+
+他のパッケージシステム(例えば Debian とかのバイナリパッケージ)にも使えるメタデータを提供できる枠組みが欲しいよね、
+あとどうせパッケージの詳細書くのだったら、そこからビルドスクリプト(Makefile とか)も生成できる方がいいよね、
+ということで、 OCamlForge の人たちが OASIS http://oasis.forge.ocamlcore.org/ というのを作っています。
+OCaml のビッグユーザである Jane Street も賛同しているので、これはメインストリームになりますから必見ですよ!
+まあ、まさに今皆でバグ出ししている最中なのでまだホットすぎるけど。
+
+   しかしこの OASIS いうのが一般名詞過ぎて検索しづらいのよね… ocaml oasis 位で検索しないとどもならん
+
+さて、その OASIS なんですが、今のところターゲットビルドシステムとして OCamlBuild を考えてる。普通の Makefile とか、私の好きな OMakefile は
+
+   OMake (todo)
+
+とか書かれていて、その時点で試す気が沸かなかったのですが、実は OMake な人でも(もちろん、ほかのビルドシステムでも)それなりに書けることが解ったので
+ちょっと触ってみることにしました。
+
+
+そもそも OASIS て何よ
+=========================================
+
+まあぶっちゃけ Cabal のパクリですわ。(だから多分、 Cabal と同じような依存地獄が出てきますよw 一応、 Cabal ユーザにどこがムカツク?ってサーベイしてたけど。)
+
+_oasis
+    ソフトウェアパッケージの名前、作者、バージョン、ライセンス、依存する他のパッケージ名、ビルドするターゲットモジュール等をつらつらと書きこむ
+setup.ml 
+    ``_oasis`` を ``oasis`` コマンドで変換すると ``setup.ml`` というファイルができる。このファイルを使ってパッケージをビルドしたりインストールしたりする
+myocamlbuild.ml
+    ``_oasis`` を ``oasis`` コマンドで変換すると OCamlBuild 用のビルドファイルが出来る。 ``setup.ml`` は実はこれを使う。(OCamlBuild じゃない人は作る必要なし
+INSTALL.txt, AUTHOR.txt
+    ``_oasis`` に必要パッケージとか、作者名とか書いといてくれたら勝手に作ってくれるんだ。英語書かなくてもいい!!
+
+あなたが ``_oasis`` とソースコードを書けば、 ``oasis`` コマンドが ``myocamlbuild.ml`` (Makefile みたいなものね) と ``setup.ml`` (configure と make みたいなコマンドインターフェース) を作ってくれる、その上、_oasis は共通フォーマットだから、(将来)それをアップしとくだけでパッケージサイト(Oasis DB)に登録されたりするわけで、もうとっても Cabal チック。パッケージに興味のある人はダウンロードして、 ``ocaml setup.ml -configure`` ``-build`` ``-install`` で完了。めでたしめでたし! という感じで、パッケージ書く人も使う人も嬉しい、ことになっています。
+
+    でも、俺の環境じゃコンパイルできねえお前何とかしろっていうスパムももれなくついてきそうだね!
+    まあ、パッチ送ってくるならともかく、デフォでガン無視だよね!
+
+OCamlBuild 以外でも OASIS が使える
+===================================
+
+さて、そんな OASIS なんだけど、今のところビルドシステムは OCamlBuild しか対応してない。んで、私は OCamlBuild 使わないんです。多分日本一 OMake 使ってますんでー。
+
+    OCamlBuild、簡単なことするんだったら、いいらしいですよ、ホント。試してみて下さいよ。
+
+        私はね、OCamlBuild との出会いが良くなかった。
+        OCamlBuild は開発時から OCaml に付属する CamlP4 や OCamlDoc をビルドできるように開発されたんだけど 、
+        両方共結構大きいアプリケーションだから、その myocamlbuild も当時世界一複雑だった。
+        それを、まず例として見てしまった、ウゲェ無理ですよ!でやめちゃったんです。
+        まあ、 hello world すっ飛ばしてコンパイラの実装を見てしまったような感じですね。
+
+    もう一度言うけど簡単なとこから始めるといいらしいよ。
+    OMake も極まってくると一見さんさようならデスカラネ。
+
+でも実は実は!別に OCamlBuild じゃなくっても OASIS 使えるんです!知らなかったんです!
+今のところ、_oasis から OMakefile の雛形を作れないってだけで、自分ですでに OMakefile とか、
+普通の Makefile 書いてる場合は問題ないのでした。(ちゃんと目立つとこにそう書いといて欲しいです…) 
+なんで、 私の(ビルドシステム的に)極まったライブラリ達を OASIS化してみようじゃあ、あーりませんか。
+
+OASIS をインストールするよ!
+===================================
+
+なんでパッケージシステムを使うのに、パッケージからじゃなくてソースからビルドしなきゃいけないんですか、ぷんぷくりーん、
+なので、バイナリを使うことにしました。
+https://forge.ocamlcore.org/frs/?group_id=54&release_id=343#oasis-0-2-0-title-content
+Linux のバイナリは…なんか GUI のインストーラが立ち上がったぞw Ubuntu だと libpcre.so.0 のリンクが問題があるようです。 ``ln -s libpcre.so.3 libpcre.so.0`` して ``LD_LIBRARY_PATH`` でおk。 ( https://forge.ocamlcore.org/tracker/?func=detail&aid=784&group_id=54&atid=291 ) 
+
+OASIS をとりあえず使ってみるよ
+=========================
+QuickStart 読めや: http://oasis.forge.ocamlcore.org/quickstart.html
+
+やる気
+-----
+とりあえず、新しいプロジェクトを始めよう! という意気込みを持つ(ふりをする。練習なので
+
+QuickStart
+----------
+新しいディレクトリ掘って ``oasis quickstart`` でもれなくアンケートに答えよう!
+変な答を入れるとまた始めからやりなおしなので、体力が必要だ! ( https://forge.ocamlcore.org/tracker/?group_id=54&atid=291&func=detail&aid=797 )
+例えばモジュール名は大文字で始めないと門前払い!
+
+適当に答えてたら MyGreatLibrary の為の ``_oasis`` ができた! 見てみよう::
+
+    OASISFormat: 0.2
+    Name:        MyGreatLibrary
+    Version:     42.0.0
+    Synopsis:    My great library
+    Authors:     My name is great!
+    License:     LGPL-2.0 with OCaml linking exception
+    
+    Library my_great_library
+      Path:            lib            # . はやめた方がいいよ
+      BuildTools:      ocamlbuild     # ocamlbuild 用スクリプトを生成してくれる
+      Modules:         Great          # 大文字で始める。 lib/great.ml を書くこと
+      InternalModules: GreatInternal  # 指定しなくてもよい
+
+この時点での注意は上にコメントで書いといた。 
+
+特に、 Path: はトップディレクトリ ``.`` でも、いいんだけど、やめといた方がいい。
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+既に自分で書いたパッケージを OASIS 化する時、特に。
+後述の ``ocaml setup.ml -ほげほげ`` する時に、トップディレクトリもサーチパスに入っているので ``stream.ml`` とか
+OCaml 標準ライブラリと同じ名前のファイルがあると爆発するんだ。
+
+ソースをでっち上げる
+-----------------
+
+次にやることは、ソースを書くこと。 ``lib/great.ml`` に君の極まったライブラリを書いてください。今回は ``touch lib/great.ml`` で許しといたるわ。
+
+oasis setup そして、設定、ビルドしてインストール!
+--------------------------------------------------
+
+``oasis setup`` で ``_oasis`` からビルドに必要な ``myocamlbuild.ml``, ``setup.ml`` をなんとなく自動生成してくれるよ。
+
+OCaml トップレベルと ``setup.ml`` を使ってビルドしてみよう!::
+
+    $ ocaml setup.ml -configure
+    ... 
+    $ ocaml setup.ml -build
+    I: Running command '.../bin/ocamlbuild lib/great.cma lib/great.cmxa lib/great.a -tag debug'
+    .../bin/ocamlopt.opt ... myocamlbuild.ml ... -o myocamlbuild
+    ocamlfind ocamldep -modules lib/great.ml > lib/great.ml.depends
+    ocamlfind ocamlc -c -g -I lib -o lib/great.cmo lib/great.ml
+    ocamlfind ocamlc -a lib/great.cmo -o lib/great.cma
+    ocamlfind ocamlopt -c -g -I lib -o lib/great.cmx lib/great.ml
+    ocamlfind ocamlopt -a lib/great.cmx -o lib/great.cmxa
+
+あ、なんか出来た…(もちろん空だけど) あとは ``ocaml setup.ml -install`` でインストールしたり、 ``-uninstall`` でアンインストールしたりできる。まったくカンタンだ。
+
+あとは、 ``_oasis`` や ``setup.ml``, ``myocamlbuild.ml`` 他、生成されたファイルを github か bitbucket に突っ込んだら一丁上がり! 
+君も OCaml デベロッパだ! おっと、 ``lib/great.ml`` も忘れないようにな!
+
+既存ライブラリを OASIS でパッケージ化してみる
+=======================================
+
+さて、ここまで読むと、なんだか OASIS って勝手に ``myocamlbuild.ml`` 作ってくれるのはいいけど、それで決め打ち見たいだし、
+「俺の極まった ``myocamlbuild.ml`` を上書きするんじゃねぇー」
+とか、
+「俺は OMake 信者だから OCamlBuild は死んでも使わねー」
+という人が出てきます。で、 OASIS 使えねー、というとそうでもないんですね!
+今度はそれを見ていきましょう!
+
+まず、トップディレクトリから .ml/.mli をサブディレクトリに移動 
+-----------------------------------------------------
+
+上でも書きましたけど、 ``ocaml setup.ml`` との相性が悪い場合があるので、トップにソースを置かないことです。
+当然、ビルドのための Makefile (OMakefile も同様、以下省略) はトップからサブを呼び出すようにします。
+
+_oasis をでっち上げる
+--------------------
+
+``oasis quickstart`` で適当に答えられるところだけ答えて ``_oasis`` を作ってしまいましょう。
+例えば、上の MyGreatLibrary みたいなので構いません。
+
+_oasis を変更しよう
+--------------------
+
+``_oasis`` を変更して、自動ビルドスクリプト生成をオフ、そしてビルドコマンドを指定します。結論から言うと OMake だとこんなファイルをつくる::
+
+    OASISFormat: 0.2
+    Name:        MyGreatLibrary          # 多分スペース無しで、小文字の方がよいかも。
+    Version:     42.0.0
+    Synopsis:    My great library        # ここはかっこいい名前を自由に書ける
+    Authors:     My name is great!
+    License:     LGPL-2.0 with OCaml linking exception
+    Plugins:      StdFiles (0.2)         # INSTALL.txt や README.txt を自動で作ってくれる。
+    BuildType:    Custom (0.2)           # ocaml setup.ml -build の時に XCustomBuild を使うおまじない
+    InstallType:    Custom (0.2)         # ocaml setup.ml -install の時に XCustomInstall を使うおまじない
+    XCustomBuild: omake                  # ビルドの時はこのコマンドをつかうぜ
+    XCustomInstall: omake install        # インストールの時はこのコマンドをつかうぜ
+    XCustomUninstall: omake uninstall    # アンインストールの時はこのコマンドをつかうぜ
+    BuildTools: omake                    # omake コマンドが無いとコンパイルできないよ!
+    
+    Library my_great_library
+      Path:          lib
+      FindlibName:   my_great_lib        # findlib で my_great_lib っていう名前にするよ
+      BuildDepends:  unix                # unix という findlib package が必要なんだ!
+      Modules:       Great,              # モジュール名はカンマで区切るんだ
+                     Greater,
+                     EvenGreater,
+                     Greatest
+
+要するに、キモは、 ``BuildType``, ``InstallType`` を ``Custom (0.2)`` に指定して、 
+``XCustomHogehoge`` にそれぞれのコマンドを書けばいいだけなんだね!
+``ocaml setup.ml -hogehoge`` は単に ``XCustomHogehoge`` のコマンドを実行するラッパになります。
+ていうか、それだけの事なんだ… OMake(todo) とか書かンといて欲しいわ…
+
+もちろん、 BuildType を Custom にすると ``oasis setup`` しても ``myocamlbuild.ml`` は生成されなくなる。
+
+    ``BuildType`` や ``InstallType`` 、そして ``ConfType`` を ``Custom (2.0)`` に指定し忘れていると
+    現時点では ``XCustomHogeHoge`` を書いてもガン無視する素敵バグがあるので注意だ!!
+
+後は、 ``ocaml setup.ml -hogehoge`` をテストしてちゃんとビルドやインストールできるか確認しよう。
+
+パッケージ化した! で、どうすんのん? *将来* OASIS DB で公開しよう
+============================================================
+
+*今じゃないぞ!*
+
+ソフトウェアを OASIS でちゃんとパッケージ化すると、 ``_oasis`` に依存情報が書きこまれているはず。
+例えば、上の例では、 ``BuildTools: omake`` とか、 ``BuildDepends: unix`` とか書いてありますね。
+例えばここにバージョン情報も書けるようです。例えば ``BuildDepends: oUnit (>= 1.0.3)`` とかね。
+findlib がバージョン 1.0.3 以上の oUnit を見つけないと ``ocaml setup.ml`` が失敗しちゃうわけです。
+
+OASIS では、この ``_oasis`` に記述された提供バージョンと、依存バージョンを使って、ああ、このパッケージには
+このパッケージが必要だな、とか、考えるわけですね。
+
+   いやー、もうこの辺りで OASIS が Ports や Cabal より、上手くいくはずが無いような気がしますが…
+   まあこれは、ソースパッケージの宿命ですよね。
+   まあ、パッチ送ってくるならともかく、デフォでガン無視だよね!
+
+様々なパッケージの様々なバージョンを管理しよう、という、パッケージレポジトリ (CPAN とか Hackage に対応するもの)が OASIS DB です。
+( http://oasis.ocamlcore.org/ ただいま準備中。人柱は http://oasis.ocamlcore.org/dev/home )
+
+あるパッケージのあるバージョンが欲しい、そういう時は OASIS DB を検索しますし、
+また、パッケージを作成して、それが検索されるようにするには OASIS DB に登録することになります。
+
+残念ながら、 OASIS DB は OASIS に輪をかけて絶賛テスト中の状態です、
+だから、おおっ、よさげ、 OASIS を使うよー、というカジュアル OCaml ユーザーは、あいや、暫く!あいや、暫く!、です。
+
+OASIS DB で公開する方法(今日現在)
+-------------------------------
+
+まず、 OASIS DB にパッケージを登録してみましょう。これは超ムズイ、というか、今のところ間違って変なものを登録すると、
+やり直せない、というドキドキ仕様です。私も spotlib-1.0.0 を変に登録してしまいました。消せません。メールして直してもらいました。
+でも多分少しでも多く皆がアップロードして盛り上げていったほうがいいと思うので、簡単にハマリポイントを説明しますね。
+
+基本的にこっから先は地雷原です。
+何かあったらすぐ思考停止して https://forge.ocamlcore.org/tracker/?atid=294&group_id=54&func=browse にレポートするのが良いみたいですね。
+
+2011/06/06: 一週間かそこらで、投稿パッケージの _oasis ファイル変更が可能になるそうです。これで間違った依存情報を上げてしまっても後から修正することができますね。
+
+OCamlForge のアカウントを作る
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+えっ、持ってないの?
+この際です。作りましょう: https://forge.ocamlcore.org/account/register.php
+
+Tarball を作る
+~~~~~~~~~~~~~~~~~~~~
+
+OASIS DB には "tarball" でソフトを提出せよ、とあるんですが、これが曲者で、どんな tarball か、まぁあああああたく、記載がないのです。
+
+    記載してクレロンってメール送っといたから何か改善されるかもしれないね
+ 
+以下は私が推測した今日現在(2011/06/05)の条件です。
+
+``xxx.tar.gz`` の形であること
+    例えば、上の例で言うと、 ``MyGreatLibrary-1.0.0.tar.gz`` でしょうか。(パッケージ名、バージョン名を持つ必要はありません)
+Tarball の中身がトップディレクトリ一つで、 ``xxx/_oasis`` を持っていること
+     ``MyGreatLibrary-1.0.0/_oasis``,  ``MyGreatLibrary-1.0.0/lib/great.ml`` ってことですね。(ディレクトリ名がパッケージ名、バージョン名を持つ必要はありません)
+.tar.gz であること
+     .tar.bz や .tbz は無理です。 .tgz はどうでしょうね。試してません。
+ 
+Tarball をどこかに置く
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+これも謎なんですが、 OASIS DB 自体に tarball をコピーして取っておいてくれるのに、他の所からも同じ tarball を入手できるように
+しなきゃいけません。 bitbucket や github とかそういうのに何かそういう機能ありますよね?そこに置きましょう。
+
+Upload しる!
+~~~~~~~~~~~~~~~~~~~~~
+
+Tarball の準備ができたら、アップします。
+
+まず、 http://oasis.ocamlcore.org/dev/home の Upload というリンクを押す
+    Upload page に移動します。今日現在、あまりに素っ気無い作りに脱力すること請け合いです
+Tar ball にローカルに存在する tar.gz ファイルを指定
+    今のところ tar.bz ダメです。 tar.gz です。  
+Public link に同じ Tar ball を http でダウンロードできる URL を入れる
+    じゃあなんで、ローカル tarball を指定せなイカンのか判りません。
+    ここで私は意味がわからなかったので、 tarball ではなくドキュメントの URL を入れてしまい、放置プレイ中です。
+Upload を押す
+    何か問題があると、全く愛想のないエラーメッセージで上手くいかなかったことがわかります。
+    何がどううまくいかなかったかは判りません (>_<)
+サマリを確認して、確定する
+    やり直しできません。漢気を感じさせる作りですね! (>_<)
+
+さて、無事に upload が済むと、 http://oasis.ocamlcore.org/dev/browse にあなたのパッケージがリストされているはず。
+
+OASIS DB からパッケージを落としてきてインストールする
+============================================================
+
+OASIS DB からパッケージを落としてきて宜しくやるには、 ODB ってパッケージャを使います: http://oasis.ocamlcore.org/dev/odb/
+``odb.ml`` てファイルを ``ocaml odb.ml`` って立ち上げるといい。 密かに curl が必要です。
+
+あるパッケージと、依存パッケージをガガっとインストールするには ``ocaml odb.ml --repo unstable <パッケージ名>`` とするようです。
+``--repo unstable`` はパッケージレポジトリの種類を選んでいます。将来的には OASIS DB の人が頑張って、これは stable、
+これは testing ってやってくれるみたいです。ホンマかいな。とりあえずは遊びですので、一番数のある unstable ですね。
+たとえば csv パッケージをインストールしてみました::
+
+   # ocaml odb.ml --repo unstable csv
+   Getting URI: http://oasis.ocamlcore.org/dev/odb/unstable/pkg/info/csv
+   Getting URI: http://oasis.ocamlcore.org/dev/odb/unstable/pkg/info/ocamlbuild
+   ...
+   Package ocamlbuild dependency satisfied: true
+   ocamlfind: Package `csv' not found
+   Package csv dependency satisfied: false
+     % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
+                                    Dload  Upload   Total   Spent    Left  Speed
+   100 64377  100 64377    0     0   8718      0  0:00:07  0:00:07 --:--:-- 10090
+   csv-1.2.2/
+   csv-1.2.2/INSTALL.txt
+   ...
+   I: Running command '.../bin/ocamlc.opt -config > '/var/tmp/oasis-b142a0.txt''
+   I: Running command '.../bin/ocamlfind query -format %v findlib > '/var/tmp/oasis-94ff1d.txt''
+   
+   Configuration: 
+   
+   ocamldoc: ...................................... .../bin/ocamldoc
+   OCamlbuild additional flags: ................... 
+   Compile with ocaml profile flag on.: ........... false
+   ...
+   
+   I: Running command '.../bin/ocamlbuild src/csv.cma src/csv.cmxa src/csv.a examples//example.native -tag debug'
+   ...
+   I: Installing findlib library 'csv'
+   I: Running command '.../bin/ocamlfind install csv src/META $HOME/.odb/install-csv/csv-1.2.2/_build/src/csv.cmi ...
+   Installed $HOME/.odb/lib/csv/csv.mli
+   Installed $HOME/.odb/lib/csv/csv.cma
+   Installed $HOME/.odb/lib/csv/csv.cmxa
+   Installed $HOME/.odb/lib/csv/csv.a
+   Installed $HOME/.odb/lib/csv/csv.cmi
+   Installed $HOME/.odb/lib/csv/META
+   ocamlfind: Package `csv' not found
+   Package csv dependency satisfied: false
+   Problem with installed package: csv
+   Installed package is not available to the system
+   Make sure $HOME/.odb/bin is in your PATH
+   and $HOME/.odb/lib is in your OCAMLPATH
+
+ふーむナルホド。 csv パッケージを取ってきて、(途中の微妙なエラーメッセージは気になりますが)ビルドして、デフォルトでは ``$HOME/.odb`` にインストールするのですね。
+うーん、 Cabal そっくりだね。ホントに Cabal と同じ問題がありそうダネ…
+最後の二行にあるように、 PATH と OCAMLPATH を設定してあげればあとは良いみたいです。
+基本的な機能は動いているみたいですね!!
+
+まとめ: みんな _oasis 書こう
+============================================================
+
+そんなこんなで OASIS 体験してみました。親指シフトより簡単です。
+見てきたように、別に OCamlBuild 使わないとダメということもありません。
+OCaml でプログラムを書いてる皆さんはとりあえずゆっくりと _oasis を書き始めてみたらいいんじゃないかな?
+
+で、余裕があれば OASIS DB に登録してみてくださいね!!

File ocaml-tools.rst

+=============================================================
+OCaml 開発環境について ~ OCaml コンパイラソース付属ツール
+=============================================================
+
+この文章では 2012年3月での関数型言語 OCaml によるプログラム開発における、必須・重要ツールを紹介する。
+まず、OCaml コンパイラ一式をインストールした際に付属する「公式」ツール群から解説する。
+
+★は重要度。五点満点。
+
+OCaml コンパイラ
+==========================
+
+現時点での公式最新バージョンは 3.12.1。
+
+次のリリースバージョンはおそらく 4.00.0。開発中の trunk バージョンは 4.01.0。 
+4.00.0 では GADT と 3.12.1 より使い易い first class module が入っている。
+2012年内のリリース予定だと思われる。
+
+このところ OCaml のマイナーバージョンの変わるリリースは一年に一度位。
+バグフィックスパッチやリリースはより頻繁にある。
+
+ocaml toplevel ★★★★
+--------------------------
+OCaml 対話環境。いわゆる REPL(Read-Eval-and-Print Loop)。
+入力は型推論の後 bytecode へとコンパイルされ VM により評価される。
+Bytecode とはいえコンパイルが入るため、インタープリタとは普通呼ばれない。
+
+Real World OCaml programmer は toplevel はまず使わない。
+
+ocaml toplevel の対話環境としての能力はあまり高くない。行の編集や履歴を呼び出したい場合は、
+
+* rlwrap : read line wrapper
+* emacs の shell mode 内などでの実行
+
+で編集能力を強化するのが普通である。
+
+(Native code へとコンパイルする ocamlnat という対話環境も存在する。ただしまだ「非公式」)
+
+ocamlc bytecode compiler ★★★★★
+---------------------------------------
+OCaml ソースコードを bytecode へとコンパイルするコンパイラ。
+Bytecode プログラムは native code と比べると遅いが、 ocamldebug を使ったデバッグが可能。
+
+ocamlopt native code compiler ★★
+-----------------------------------------
+OCaml ソースコードを native code (マシン語)へとコンパイルする。 
+Native code がサポートされているアーキテクチャで OCaml コンパイラソースコードディレクトリで make opt すると作成される。
+実はほとんど使わない。次の ocamlc.opt, ocamlopt.opt を参照のこと。
+
+ocamlc.opt ocamlopt.opt ★★★★★
+---------------------------------------
+Native code にコンパイルされた bytecode および native code コンパイラ。
+Native code コンパイルが可能な環境では通常このコンパイラを使う。
+
+OCaml コンパイラソースコードで make opt の後に make opt.opt を行うと作成される。
+通常の ocamlc, ocamlopt は bytecode で実行される。 
+\*.opt コンパイラは native にコンパイルされているため bytecode へとコンパイルされたコンパイラより実行速度が早い。
+(Bytecode 版コンパイラがひどく遅いわけではない。)
+
+ocamlc, ocamlopt 以外のツールにも、 .opt の postfix がついた native code バージョンが存在する。
+
+ocamldep ★★★★★
+=================
+ocamldep は複数の OCaml プログラムファイル間の依存関係を抽出するツール。
+結果は Makefile の依存書式で出力される。通常は、
+ocamldep \*.ml \*.mli > .depend
+として依存情報をファイルに書きだし、それを Makefile 等で include する。
+
+使い方の例は、 Makefile を使った OCaml ソフトウェアを見れば、まず使用されているので、それらを参考に。
+
+OCaml パーサーツール
+================================
+
+OCaml では lex-yacc スタイルのパーサツールが標準で付属しており、
+このパーサによって OCaml の文法自体も定義されている。
+
+ocamllex ★★★★
+---------------------------
+Multi-byte char を処理する場合は、 ulex を使うべきである。
+
+Lexical analyser。 Lex のスタイルを踏襲しつつ、アクション等のコードを OCaml プログラムで記述できる。
+そのため、基本的に lexer (字句解析)や正規表現の知識が有用かつ前提である。
+ocamllex は \*.mll というアクション等のコードを OCaml プログラムで記述できる。
+\*.mll の例は OCaml コンパイラソースの parsing/lexer.mll を参考にするといい。
+
+ocamlyacc ★★★★
+--------------------------
+ほとんど上位互換で、エラーメッセージの読みやすい Menhir を使うべきである。
+
+Parser generator。こちらは yacc のスタイルを踏襲し、アクション等のコードを OCaml プログラムで記述できる。
+そのため、 yacc の知識が必要。例えば shift-reduce, reduce-reduce の知識がなければ使いこなせない。
+ocamlyacc は \*.mly という拡張子のファイルを受け取り、 parsing rule を解釈し、 \*.ml へと変換する。
+注意すべき点として、 OCaml コード以外のパートでのコメントは (\* ... \*) ではなく、 /\* ... \*/ であることが挙げられる。
+\*.mly の例は OCaml コンパイラソースの parsing/parser.mly を参考に。
+
+ocamllex, ocamlyacc は色々と古臭い部分もあり、イライラすることもあるが、
+ほとんどアップデートもなく、非常に良く枯れているツールであるともいえる。
+
+ocamlyacc のほぼ上位互換 parser generator として Menhir という外部ツールがある。 Menhir は ocamlyacc と同じ \*.mly ファイルを受け取る上に、エラーメッセージが読みやすいなど良い点が多い。そのため、現在 OCaml で parser generator を使う場合は Menhir を使うことが推奨されている。
+(ユーザに Menhir をインストールさせるのが面倒だと思われる場合は、 Menhir で新しい機能を使わず、デバッグ開発を行い、リリース時には ocamlyacc に戻す、ということも可能。)
+
+Camlp4 pre-processor and pretty printer ★★★
+====================================================
+Camlp4 (略称P4) は Pre-Processor and Pretty Printer の4つの P から P4 と呼ばれ、
+自分でパーサーをスクラッチから記述できるだけでなく、 
+OCaml コードでのマクロや文法拡張を実現することもできる強力なツール。
+P4 は yacc のような LALRベースではなく、 LLベースの stream parsing が使われるため、
+ocamlyacc と camlp4 では文法記述法が異なる。
+
+P4 では OCaml の文法が stream parsing で再定義されており、
+このパーサーを使って OCaml プログラムを解釈し、その結果を OCaml コンパイラに送ることができる
+(OCaml 標準の lex-yacc で書かれたパーサーは迂回される)。
+使い方は OCaml コンパイラの -pp オプションを見ること。
+
+この P4 の OCaml parsing rule群を動的に変更することで、 OCaml の文法を拡張することができ、
+単純なマクロから、非常に複雑なメタプログラミングまで P4 が活躍する。
+高レベルな OCaml プログラミングでは、P4 を利用した複数の文法拡張をしばしば利用するため、
+複雑ではあるが非常に重要なツールである。
+文法拡張記述には OCaml の通常の文法 (original syntax) と
+OCaml 文法拡張を書く際、 ambiguity が少なくなる改良文法 (revised syntax) の二つの文法を
+選ぶことができる。これらの文法を使うかどうかに対応して Camlp4 コマンドも camlp4* から始まる複数のコマンド群からなる。
+
+問題は、 P4 は非常に複雑なツールであるため、 OCaml 本体の正式文法が拡張された場合、それへの追随が遅れることがあること
+(よって、新機能と P4 の組み合わせが使えなかったりする)、そして、ドキュメントがほとんど整備されていないこと、である。
+既存の P4 で書かれた文法拡張を使うだけの場合は P4 でのパーサルールの書き方などを理解する必要はないとはいえ改善が望まれる。
+
+以下は 3.10系 Camlp4 を開発した人が書いた情報。残念ながら全く不十分
+
+* Camlp4: Major changes : http://nicolaspouillard.fr/camlp4-changes.html
+* Using Camlp4: http://brion.inria.fr/gallium/index.php/Using_Camlp4
+
+3.10系 P4 のチュートリアルとしては Jake Donham の
+Reading Camlp4 http://ambassadortothecomputers.blogspot.com/search/label/camlp4
+は素晴らしい記事であり、推薦する。
+
+インターネット上の P4 の情報を調べる際は、必ずそれがいつの時期に書かれたものか確認すること。
+
+Camlp5 との関係
+-------------------
+Camlp4 とは別に Camlp5 というツールが存在するが、これは OCaml に同梱されていない。
+
+Camlp5 は OCaml version 3.09 まで同梱されていた Camlp4 が引継がれたもので、
+Version 3.10 以降の OCaml 同梱の Camlp4 はリライトされ、その際に大幅に refactoring されている。
+そのため、コードベースとしては 「3.09 までの P4」 および P5 は似ている。 3.10系 P4 は
+それらからかなり離れている。 P5 が P4 より数字が多いため、優れているとか、その逆、という関係ではない。
+なお、 P5 は Coq theorem prover でよく使用されている。
+
+基本的にこれら P4, P5 のアイデアは同じなので 古い P4 および P5 のドキュメントを読んで 3.10系 P4 の基本的な使用方法を理解することは可能であるが、その際には必ず 3.10系 P4 の working example などを参照して細かな違いを把握する必要がある。
+
+P4 と P5 が何故ブランチしたか、はさまざまな事情があるがここで語るべきではない。
+
+ocamlmktop, ocamlmklib ★★★
+================================
+まだ書いてない
+
+ocamldoc ★★
+=======================
+まだ書いてないよく知らない
+
+ocamlbuild ★★★
+======================
+まだ書いてないよく知らない
+
+エディタ支援
+==================================
+
+公式ソースコードに付属するエディタ支援は Emacs, XEmacs の物に限られる (Emacs24 動作未確認)
+ソースコードからビルドしている場合、 make install ではこれらの elisp ファイルはインストールされない。
+導入にはソースディレクトリ/emacs/README を読むこと。
+
+caml.el ★★★★★
+------------------------
+OCaml プログラムのインデントとハイライトを提供する Caml-mode を提供する。
+外部ツールである tuareg-mode を好む人もいる。
+
+caml-types.el ★★★★★
+----------------------------
+任意の部分式の型を表示させることで型エラー解消などの作業を効率的に行うためのツール。
+
+OCaml コンパイラ(ocamlc, ocamlopt)に -annot オプションを付けて \*.ml, \*.mli ファイルを
+コンパイルすると \*.annot というファイルができる。この \*.annot ファイルにはソースコード
+上の場所をキーとして、そこにある式の型などの情報が記録されいる。
+caml-types.el はこのファイルを走査し、部分式の型を Emacs のメッセージバッファに表示する。
+
+caml-types.el は caml.el と独立しており、 tuareg-mode と一緒に使うこともできる。
+
+caml-debug.el ★★
+----------------------
+ocamldebug を Emacs で使うための elisp。現在実行中のソースコードの場所などを Emacs 中に表示できる。
+
+ほとんど使用されないツール
+====================================
+
+バイトコードデバッガ ocamldebug ★
+------------------------------------------
+
+ごくたまに利用される程度である。
+
+ocamldebug は OCaml の byte code プログラムのためのデバッガ。
+ocamldebug を使うためには各バイトコードオブジェクトファイル \*.cmo を 
+ocamlc にデバッグフラグ -g を付けてコンパイルする必要がある。
+
+ocamldebug では一旦進めたデバッグステップを巻き戻すことができるという、ちょっと変わった機能がある。とは言え… printf デバッグか、 gdb を使った native code プログラムのデバッグの方が判りやすい場合が多い。どうしてもプログラム挙動がわからない場合、念のために使われることが多い。これは ocamldebug が非力だからというのではなく、やはり静的に型付けされた関数型プログラムではキャストの誤りや NULL エラーが起こることがなく、あまりデバッグを必要としないからというのが大きい。
+
+バイトコードプロファイラ ocamlprof と ocamlcp ★
+---------------------------------------------------------
+
+ほとんど利用されない。
+
+ocamlprof は byte code プログラムのためのプロファイラ。
+ocamlprof を利用するためには各バイトコードオブジェクトファイルは
+ocamlcp という ocamlc のラッパを用いてコンパイルされていなければならない。
+
+ocamlcp でコンパイルされた byte code 実行ファイルを実行すると
+ocamlprof.dump というファイルが作成される。
+これを ocamlprof コマンドを使って関数などの使用回数を抽出、
+元のソースファイル内にコメントとして書きだす。
+
+ocamlprof は呼び出された回数しかプロファイルしないので利用されない。
+
+OCaml プログラムでプロファイルを取る場合は、通常
+ocamlopt に -p オプションを付けて native code でのプロファイルを取り、
+そのアプトプットを gprof で可視化するのが普通である。
+
+マニアックなツール
+==================
+
+expunge 
+--------
+
+ocamlobjinfo
+---------------