Ocaml lecture slides 01 at axsh

1,993 views
1,959 views

Published on

This slide is simple Objective Caml Tutorial, used in Axsh at 6/5.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,993
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Ocaml lecture slides 01 at axsh

  1. 1. OCaml勉強会@axsh(はじめのいっぽ)<br />Id:s1061123<br />
  2. 2. Ocamlとは<br />Ocaml = Objective Camlの略<br />
  3. 3.
  4. 4. 公式ページにOcamlって書いてない!!!<br />公式ページはhttp://caml.inria.fr/index.en.htmlです.<br />
  5. 5. Objective Caml勉強会@axsh(はじめのいっぽ)<br />Id:s1061123<br />
  6. 6. OcamlObjective Camlとは<br />Objective Caml= Caml言語のObject拡張版<br />CamlとはフランスのINRIAという研究所で開発された関数型言語で↓等々を供えた言語<br />型システム(型推論・多相型)<br />パターンマッチング<br />Ocamlはそれに↓を追加した言語<br />モジュールシステム<br />オブジェクト機能<br />Native Compiler(ネイティブバイナリ吐ける!)<br />
  7. 7. Objective Camlの親戚一覧<br />ML系列 (Objective Camlと同類)<br />F# (for .Net) http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/default.aspx<br />Standard ML of New Jersey (SML/nj) http://www.smlnj.org/<br /> Alice http://www.ps.uni-saarland.de/alice/<br />SML# http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/<br />Haskell<br />Closure<br />Concurrent Clean<br />Lisp/scheme<br />
  8. 8. 特徴<br />型推論があるので(ある程度)プログラムのエラーを静的に解析できる<br />パターンマッチによって複雑な条件式が簡潔に書ける<br />高階関数(Higher Order Function)や多相型(Polymorphic Type)によってより柔軟な処理の記述が可能<br />
  9. 9. 最終的なGoal<br />Ocamlのプログラムのコンパイルの仕方,実行方法が分かるようになる<br />関数型言語の知識が(少し)分かるようになる(型推論とか,パターンマッチングとか…)<br />関数型言語っぽいプログラミングのマナーを知る(再帰脳・リスト指向・高階関数使用)<br />
  10. 10. 目次<br /><ul><li>データ構造体
  11. 11. リスト・ペア
  12. 12. レコード
  13. 13. バリアント
  14. 14. パターンマッチ
  15. 15. 再帰
  16. 16. 多相型について
  17. 17. 多相型関数
  18. 18. 多相型データ</li></ul>インストール<br />“Hello world!”<br />プログラムの起動・終了<br />プログラムの解説<br />その他<br />型について<br />関数<br />関数定義<br />条件分岐<br />再帰<br />
  19. 19. インストール<br />Windows: Cygwin/MinGW/MSのどちからを選択.<br />違いはビルド環境<br />ライブラリ,生成コードのインターフェイスに違い<br />詳しくは公式ページ(http://caml.inria.fr/ocaml/portability.en.html)<br />ちなみに僕はMinGWをよくインストールします<br />Tcl/Tk(Active TCL)をインストールすると吉<br />Object Browser(リファレンス)が使えます<br />OcamlベースのF#をインストールするというのも…<br />
  20. 20. インストール<br />Mac: <br />Intel版を公式サイトからダウンロード<br />MacPortsからインストール<br />Unix/Linux:<br />ソースから頑張る<br />gccインストールよりは確実に楽です<br />パッケージはいろいろあります<br />Gentoo/Redhat/Debian for Linux<br />Ports/pkgsrc for *BSD<br />
  21. 21. とりあえずhello world!<br />Nativeバイナリ版はあとで解説しまつ<br />Windowsで<br />Unixで<br />
  22. 22. 解説<br />kagaribi% ocaml<br /> Objective Caml version 3.10.2<br /># print_string "hello world!";;<br />hello world!- : unit = ()<br /># ^D<br />kagaribi%<br />プログラムの入力<br />プロンプト<br />出力<br />プログラムの型<br />”^d”で終了<br />
  23. 23. プログラム解説<br /># print_string“hello world!”;;<br />関数名<br />引数<br />ターミネーター<br /><ul><li>引数渡す際にかっこ”()”やコンマ”,”は不要
  24. 24. 文字列は””で囲む
  25. 25. プログラムを評価したい場合には”;;”を末尾に
  26. 26. 評価については2枚後で説明
  27. 27. print_stringは文字列を受けとって表示する関数</li></li></ul><li>プログラム解説<br />hello world!- : unit = ()<br />標準出力<br />プロンプト<br />結果の型<br />返り値<br />Print_stringの結果の表示の後に評価の結果を表示<br />unitというのは型の一つでvoidみたいなもの <br />型についてはあとで説明<br />“()”はunit型の値<br />他の例<br /># 10 + 20;;<br />- : int = 30<br />#<br />
  28. 28. “評価”とは?<br />与えられたOcaml式をコンピュータが解析すること<br />関数に全ての引数が与えられたら実行<br />kagaribi% ocaml<br /> Objective Caml version 3.10.2<br /># print_string “test string”;;←関数に引数を加えて評価<br />test string- : unit = ()←実行される<br /># 10;;←数字を評価<br /><ul><li>: int = 10←評価の結果は変わらず</li></ul># print_string;;←関数を評価すると?<br />- : string -> unit = <fun>←関数が返ってくる<br />#<br />
  29. 29. Type, Type, Type!!! (1)<br />型推論する関数型言語にとって型は命です<br />int :31bit整数型 (Int32, Int64という型もあります)<br />float : 不動小数点型 (doubleっぽい)<br />string : 文字列型 (“test” で表記)<br />char : 文字型(‘a’ で表記)<br />bool : true/false<br />unit : 値を返さない型.値は()のみ<br />T1 ->T2: 型T1の値を引数でT2の型の値を返す関数の型<br />
  30. 30. Type, Type, Type!!! (2): 例<br />kagaribi% ocaml<br /> Objective Caml version 3.10.2<br /># 10;;<br />- : int = 10<br /># 10.1;;<br />- : float = 10.1<br /># "test";;<br />- : string = "test"<br /># 'a';;<br />- : char = 'a'<br /># true;;<br />- : bool = true<br /># false;;<br />- : bool = false<br /># ();;<br />- : unit = ()<br /># print_string;;<br />- : string -> unit = <fun><br />
  31. 31. 目次<br /><ul><li>データ構造体
  32. 32. リスト・ペア
  33. 33. レコード
  34. 34. バリアント
  35. 35. パターンマッチ
  36. 36. 再帰
  37. 37. 多相型について
  38. 38. 多相型関数
  39. 39. 多相型データ</li></ul>インストール<br />“Hello world!”<br />プログラムの起動・終了<br />プログラムの解説<br />その他<br />型について<br />関数<br />関数定義<br />条件分岐<br />再帰<br />
  40. 40. 関数/条件分岐<br />変数の定義・関数の定義<br />letfoobar = 10;;<br />letfoobar = 15<br />andfoobar2 = 20;;<br />lettestfunc a = <br />print_string “answer is “;<br />print_int (a + 30) ;;<br />lettestfunc a b = a + b;;<br />lettestfun a:int = a;;<br />スコープ付き変数・関数の定義<br />letfoobar = 10 in foobar + 10 ;;<br />名前無し関数(closure)定義<br /> fun a -> a + 10;;<br /> let testfunc a b = a + b;; ===== let testfunc = fun a b -> a + b;;<br />これは再代入とは違うので注意!!<br />(新規に領域を作って名前をbindしている)<br />連続した命令は”;”で分ける<br />引数の型は明示的にも宣言可<br />
  41. 41. 関数/条件分岐<br />条件分岐<br /> let testFunc a b = <br /> if (a > b) then<br /> a<br /> else <br /> b<br />If 式自身も値を返す構文であることに注目<br />そのためにelseは必須<br />
  42. 42. 関数/条件分岐<br />If節の中に複数の命令を入れる場合は注意が必要<br />条件分岐<br /> let testFunc a b = <br /> if (a > b) then<br /> (print_string “a > b”; a)<br /> else <br /> (print_string “a =< b”; b)<br />括弧の中を左から評価して最後の値を返す<br />注意:最後以外はunitを返さないとwarning<br />()の代わりにbegin … endでもOK<br />
  43. 43. 繰り返し命令<br />While/forはありますがそれを使うのは<br />
  44. 44. 繰り返し<br />繰り返しは再帰で書く.これ,最強.<br />コンパイラが最適化しやすい<br />再帰する場合は”let” -> “let rec”で書きます<br />let rectestFun a = <br /> if (a < 1) then <br /> 0 <br /> else<br /> a + testFun (a-1)<br />しかし再帰ってスタックオーバーフローするんじゃ…?<br />↑ > 末尾再帰(tail recursion)すれば大丈夫です<br />
  45. 45. 末尾再帰(tail recursion)の勧め<br />末尾再帰とは再帰の一種で再帰呼出以降に命令が存在しない再帰の呼び方<br />イメージ的には再帰で返ってくる時に値を返す以外のことをしないような再帰<br />この場合スタックは呼ばれた回数に比例して増大<br />let rectestFun a = <br /> if (a < 1) then <br /> 0 <br /> else<br /> a + testFun (a-1)<br />非末尾再帰<br />A = 10<br />A = 0<br />A = 10<br />1+0<br />2+1<br />3+3<br />10+45 = 55<br />
  46. 46. 末尾再帰(tail recursion)の勧め<br />関数型言語の場合,末尾再帰の呼出し最適化によって再帰呼びだしは最適化されてジャンプ命令になる->スタック使わない<br />よってスタックの増減は再帰回数に依存して増加しない<br />返すべき値を引数に渡すと案外簡単に末尾再帰に<br />let testFunc a = <br /> let rectestFun1 a b = <br /> if (a < 1) then <br /> b<br /> else <br />testFun1 (a-1) (b+a) <br /> in testFun1 a 0<br />testFun1 10 0<br />testFun1 9 10<br />testFun1 8 19<br />…<br />testFun1 0 55<br />末尾再帰!<br />A = 10<br />A = 0<br />A = 10<br />testFun1 10 0<br />testFun1 0 55<br />55<br />
  47. 47. 末尾再帰(tail recursion)の勧め<br />let rectestFun a = <br />if (a < 1) then<br /> 0 <br />else a + testFun (a-1)<br /># testFun 100000000;;<br />Stack overflow during evaluation (looping recursion?).<br />非末尾再帰で一億<br />let rectestFun a b = <br />if (a < 1) then <br /> b<br />else <br />testFun (a-1) (b+a)<br /># testFun 1000000000;;<br />- : int = 5000000050000000<br />末尾再帰で十億<br />末尾再帰を思い付く(->再帰脳)は関数型言語の壁の一つ<br />OcamlだけではなくHaskell, Closureでも使えるスキルなので是非!<br />
  48. 48. このあたりで休憩とか<br />
  49. 49. 目次<br /><ul><li>データ構造体
  50. 50. リスト・ペア
  51. 51. レコード
  52. 52. バリアント
  53. 53. パターンマッチ
  54. 54. 多相型について
  55. 55. 多相型関数
  56. 56. 多相型データ</li></ul>インストール<br />“Hello world!”<br />プログラムの起動・終了<br />プログラムの解説<br />その他<br />型について<br />関数<br />関数定義<br />条件分岐<br />再帰<br />
  57. 57. リスト<br />関数型言語ではリスト(linked list)を基本データとして扱っています<br /># [10; 20; 30];;<br /><ul><li>: int list = [10; 20; 30]</li></ul># 10 :: [20; 30];;<br /><ul><li>: int list = [10; 20; 30]</li></ul># 10 :: (20 :: [30]);;<br /><ul><li>: int list = [10; 20; 30]</li></ul># 10 :: (20 :: (30 :: []));;<br />- : int list = [10; 20; 30]<br />#<br />10<br />20<br />30<br />car<br />cdr<br /><ul><li>リストは先頭の要素(car)と後続のリスト(cdr)で構成
  58. 58. []で空リストを表現
  59. 59. car と cdrの連結には “::”を使用
  60. 60. リスト操作については解説しませんが一回再帰で書いておくと吉</li></ul> ↑これも関数型言語共通のマナーです(リスト&再帰脳)<br />
  61. 61. ペア<br />複数の型を組み合わせたペアの構造体<br />要素に名前はつかない<br /># (10, 20);;<br /><ul><li>: int * int = (10, 20)</li></ul># (10, 10.200);;<br /><ul><li>: int * float = (10, 10.2)</li></ul># (10, "teststr", 30.2);;<br /><ul><li>: int * string * float = (10, "teststr", 30.2)</li></ul># let pair = (10, "teststr", 30.2);;<br />val pair : int * string * float = (10, "teststr", 30.2)<br />
  62. 62. レコード<br />レコード定義c<br />C言語でいう構造体<br /># type pair_of_ints = { a : int; b : int; };;<br />type pair_of_ints = { a : int; b : int; }<br /># {a = 10; b = 20};;<br />- : pair_of_ints = {a = 10; b = 20}<br /># let p = {a = 10; b = 20};;<br />val p : pair_of_ints = {a = 10; b = 20}<br /># p.a;;<br />- : int = 10<br /># let {a=k; b=l} = p;;<br />val k : int = 10<br />val l : int = 20<br />書けば型は推論<br />取るときは”.”を使って<br />こうやってもOK<br />
  63. 63. バリアント<br />関数型言語ならではの構造体<br />イメージとしてはCのenum + union<br />typedefstructfoobar_ { <br />enum type_ {<br />TEST_VOID,<br />TEST_INT,<br />TEST_FLOAT,<br />TEST_CHAR } type;<br /> union { <br />inti;<br /> float d;<br /> char c; <br /> } val;<br />} foobar;<br /># type foobar = Void | Int of int | Float of float | Char of char | Pair of (int * int);; <br />type foobar =<br /> Void<br /> | Int of int<br /> | Float of float<br /> | Char of string<br /> | Pair of (int * int)<br />非常にシンプル!<br />
  64. 64. バリアント<br /># type foobar = Void | Int of int | Float of float | Char of string | Pair of (int * int);; <br />type foobar =<br /> Void<br /> | Int of int<br /> | Float of float<br /> | Char of string<br /> | Pair of (int * int)<br /># Void;;<br />- : foobar = Void<br /># Int 20;;<br />- : foobar = Int 20<br /># Pair (20, 20);;<br />- : foobar = Pair (20, 20)<br />使用例: option<br /># None;;<br />- : 'a option = None<br /># Some 10;;<br />- : int option = Some 10<br />
  65. 65. パターンマッチ<br />データのパターン(型の構造)で条件分岐が可能!<br />let foobarToStr = function<br /> Void -> "void"<br />|Inti-> "Int(" ^ (string_of_inti) ^ ")"<br />| Float f -> "Float(" ^ (string_of_float f) ^ ")"<br />| Char c -> "Char(" ^ c ^ ")"<br /> | Pair (a, b) -> "Pair(" ^ (string_of_int a) ^ ", " ^ (string_of_int b) ^ ")";; <br />valfoobarToStr : foobar -> string = <fun><br />int -> stringの変換:string_of_int<br />文字列の結合: ^<br /># foobarToStr Pair(10,20);;<br />This function is applied to too many arguments,<br />maybe you forgot a `;'<br /># foobarToStr (Pair(10,20));;<br />- : string = "Pair(10, 20)"<br /># foobarToStr Void;;<br />- : string = "void"<br />
  66. 66. パターンマッチ<br />パターンマッチの方法は3種類<br /># let p = Pair(10,20);;<br />val p : foobar = Pair (10, 20)<br /># let Pair(a,b) = p;;<br />Warning P: this pattern-matching is not exhaustive.<br />Here is an example of a value that is not matched:<br />(Char _|Float _|Int _|Void)<br />val a : int = 10<br />val b : int = 20<br /># let p = (10,20);;<br />val p : int * int = (10, 20)<br /># let (a, b) = p;;<br />val a : int = 10<br />val b : int = 20<br /># let (a, _) = p;;<br />val a : int = 10<br />#<br />単に値を取る場合<br />しかしやや強引<br />ペア等には有効<br />“_”で値を無視<br />
  67. 67. パターンマッチ<br /># let foobarToStr a =<br /> match a with<br /> Void -> "Void"<br /> | Int a when a > 100 -> "BigInt"<br /> | Int _ -> "Int"<br /> | _ -> "Others";;<br />valfoobarToStr : foobar -> string = <fun><br /># foobarToStr (Int 10);;<br />- : string = "Int"<br /># foobarToStr (Int 200);;<br />- : string = "BigInt"<br /># let foob# let foobarToStr a =<br /> match a with<br /> Void -> "Void"<br /> | Int _ -> "Int"<br /> | Int a when a > 100 -> "BigInt"<br /> | _ -> "Others";;<br />Warning U: this match case is unused.<br />valfoobarToStr : foobar -> string = <fun><br /># foobarToStr (Int 200);;<br />- : string = "Int"<br />When で<br />条件追加<br />比較は上から順番なのでこの場合BigIntが無視<br />
  68. 68. 多相型データ・関数<br />ペアの右を返す関数<br /># let getRight(_, a) = a;;<br />valgetRight : 'a * 'b -> 'b = <fun><br />‘a , ‘b : “型”の変数で’どんな型が来ても構わない’ということ.<br />‘a と’bが同じでも構わない.ただし一回目の’bと二回目の’bは同じ<br /># let getHead (h::t) = h;;<br />Warning P: this pattern-matching is not exhaustive.<br />Here is an example of a value that is not matched:<br />[]<br />valgetHead : 'a list -> 'a = <fun><br /># let getHead l = match l with (h::t) -> Some h | [] -> None;;<br />valgetHead : 'a list -> 'a option = <fun><br />どんな型のリストも対応する関数<br />
  69. 69. 多相型データ・関数<br />多相型レコード<br /># type 'a pairs = { a : 'a ; b : int; };;<br />type 'a pairs = { a : 'a; b : int; }<br /># type 'a tree = None | Node of ('a * 'a tree * 'a tree);;<br />type 'a tree = None | Node of ('a * 'a tree * 'a tree)<br /># Node(10, Node(20, None, None), Node(30, None, None));;<br />- : int tree = Node (10, Node (20, None, None), Node (30, None, None))<br />#<br />多相型バリアントで<br />バイナリツリー<br />10<br />20<br />30<br />
  70. 70. 次回予告<br />多相型関数<br />実際例(foldを用いて)<br />例外<br />参照<br />モジュール<br />オブジェクト<br />
  71. 71. お勧めリンク<br />http://ocaml.jp/<br />http://www.ocaml-tutorial.org/ja<br />マニア向けのリンク<br />http://ocaml.janestreet.com/?q=node/13<br />(fromhttp://d.hatena.ne.jp/camlspotter/20090906 )<br />余談:“Practical OCaml”という本は駄目らしいです<br />

×