~sumii/class/proenb2010/ml4/

Slides:



Advertisements
Similar presentations
プログラミング演習B ML編 第1回 2006/6/20 (通信コース) 2006/6/28 (情報コース) 住井 ~sumii/class/proenb2006/ml1/
Advertisements

(Rubyistのための) 超音速:ML入門
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
7/10 if 文課題 力作が多くて感心! 演習1:キーボードから2つの整数を入力し、小さい方の数字を 表示せよ。
関数(1) 第11回 [6月29日、H.16(‘04)] 今日のメニュー 1 前回の課題 2 前回の宿題 3 いろいろな関数の演習 4 課題
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第4回 配列(2) 情報・知能工学系 山本一公
ML 演習 第 1 回 佐藤 春旗, 山下 諒蔵, 前田 俊行 May 30, 2006.
コンパイラ 2011年10月17日
プログラミング言語としてのR 情報知能学科 白井 英俊.
ソフトウェア基礎科学 授業資料: 論理関係(logical relations)のお話
ファーストイヤー・セミナーⅡ 第8回 データの入力.
2006/11/30 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング基礎I(再) 山元進.
型宣言 (Type Declarations)
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
型宣言(Type Declarations)
2006/10/19 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井英二郎
条件式 (Conditional Expressions)
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
コンパイラ 2012年10月15日
2007/1/11 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
ML 演習 第 7 回 新井淳也、中村宇佑、前田俊行 2011/05/31.
プログラミング言語論 第12回 関数型プログラミング 情報工学科 篠埜 功.
2007/6/5(通信コース)2007/6/6(情報コース) 住井
~sumii/class/proenb2010/ml1/
PROGRAMMING IN HASKELL
第10回関数 Ⅱ (ローカル変数とスコープ).
プログラミング演習I 2003年5月7日(第4回) 木村巌.
~sumii/class/proenb2009/ml1/
アルゴリズムとデータ構造 第3章 ヒープ 6月10日分
1   1.テキストの入れ替え テキストを自由に入れ替えることができます。 フチなし全面印刷がおすすめです。 印刷のポイント.
1 2 1.写真の入れ替え 2.テキストの入れ替え 印刷のポイント [書式]タブの[図の変更]から好きな写真を入れ替えることができます。
ペットへの コメント Sun Mon The Wed Thu Fri Sat
情報処理Ⅱ 第2回:2003年10月14日(火).
コンパイラ 2011年10月20日
C言語 はじめに 2016年 吉田研究室.
15.cons と種々のデータ構造.
2007/6/12(通信コース)2007/6/13(情報コース) 住井
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分
アルゴリズムとデータ構造 第3章 ヒープ 5月31日分の復習
XXXXXX高校 XX期生 卒業記念 CALENDAR ▶ MON TUE WED THU FRI SAT SUN
Type Systems and Programming Languages
基礎プログラミング演習 第6回.
第6回レポート解説 条件1 条件2 条件3 月の入力 月、日、曜日の表示 日の入力 曜日の入力
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
第14回 前半:ラムダ計算(演習付) 後半:小テスト
1 2 1.写真の挿入 サンプル写真内の画像アイコンをクリックすると、「ライブラリ」から好きな写真を挿入することができます。
1 2 1.写真の挿入 サンプル写真内の画像アイコンをクリックすると、「ライブラリ」から好きな写真を挿入することができます。
ウェブデザイン演習 第6回.
~sumii/class/proenb2010/ml2/
~sumii/class/proenb2009/ml4/
2006/7/18(通信コース)2006/7/26(情報コース) 住井
2006/6/27(通信コース)2006/7/5(情報コース) 住井
2008/7/16(情報コース)2008/7/22(通信コース) 住井
~sumii/class/proenb2009/ml6/
情報処理Ⅱ 2005年10月28日(金).
地域情報学 C言語プログラミング 第3回 入力、if文、for文 2016年11月25日
関数型言語の基礎 型なしl計算 型理論 構成的プログラミング GUIにあらわれる関数概念 PBD VL
~sumii/class/proenb2010/ml5/
プログラミング基礎演習 第4回.
プログラミング基礎a 第3回 C言語によるプログラミング入門 データ入力
1 2 1.写真の挿入 サンプル写真内の画像アイコンをクリックすると、「ライブラリ」から好きな写真を挿入することができます。
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
PROGRAMMING IN HASKELL
地域情報学 C言語プログラミング 第3回 入力、if文、for文 2017年11月1日
プログラミング基礎a 第3回 C言語によるプログラミング入門 データ入力
復習 いろいろな変数型(2) char 1バイト → 英数字1文字を入れるのにぴったり アスキーコード → 付録 int
2007/6/26(通信コース)2007/6/27(情報コース) 住井
Presentation transcript:

http://www.kb.ecei.tohoku.ac.jp/ ~sumii/class/proenb2010/ml4/ プログラミング演習B ML編 第4回 2010/6/29(コミ) 2010/6/30(情報・知能) 住井 http://www.kb.ecei.tohoku.ac.jp/ ~sumii/class/proenb2010/ml4/

今日のポイント 匿名関数、部分適用 レコードとレコード型 バリアントとバリアント型 パターンマッチング

レポートについて 電気・情報系内のマシンから http://130.34.188.208/ (情報・知能) にアクセスし、画面にしたがって提出せよ。締め切りは一週間後厳守。 初回は画面にしたがい自分のアカウントを作成すること。 「プログラム」のテキストボックスがある課題では、 プログラムとしてsmlに入力した文字列のみを 過不足なく正確にコピー&ペーストして提出せよ。 (smlの出力は「プログラム」ではなく考察に含めて書くこと。) プログラムの課題でも必ず考察を書くこと。 提出したレポートやプログラムの実行結果は「提出状況」から 確認できる。 質問はml-enshu@kb.ecei.tohoku.ac.jpにメールせよ。 レポートの不正は試験の不正と同様に処置する。

復習:高階関数 「関数を引数として受け取る」あるいは 「関数を結果として返す」ような関数 「関数」自体を値として受け取ったり 返したりできる fun diff f = let fun f' x = (f (x + 0.001) - f x) / 0.001 in f' end

匿名関数 fn 引数名 => 式 letやfunで名前をつけて関数を定義するのが面倒なとき、 という式により、名前をつけずに 関数そのものを表すことができる。

例 - fun diff f = = fn x => = (f (x + 0.001) - f x) = / 0.001 ; = / 0.001 ; val diff = fn : (real -> real) -> real -> real - (diff Math.exp) 1.0 ; val it = 2.71964142253 : real

ちなみに… fun succ x = x + 1 は val succ = fn x => x + 1 と同じ fun sum n = if n=0 then 0 else sum(n-1)+n は val rec sum = fn n => if n=0 then 0 else sum(n-1)+n と同じ 再帰関数をvalで定義するときはrecが必要

「複数の引数をとる」関数に、 一部の引数だけ与えて使う 部分適用 「複数の引数をとる」関数に、 一部の引数だけ与えて使う - fun distance x y = = Math.sqrt (x * x + y * y) ; val distance = fn : real -> real -> real - val distance1 = distance 1.0 ; val distance1 = fn : real -> real - distance1 1.0 ; val it = 1.41421356237 : real - distance1 2.0 ; val it = 2.2360679775 : real

ちなみに… fun distance x y = Math.sqrt (x * x + y * y) は val distance = fn x => fn y => Math.sqrt (x * x + y * y) と同じ MLでは、厳密には「複数の引数をとる関数」は存在せず、「関数を返す関数」の一つとして表現されている

課題4. 1 前回の課題3. 3の関数deltaを、letを使わずfnで書け。 前回の例題の関数composeを、letを使わずfnで書け。 前回の課題3. 6の関数のそれぞれを、funを使わずvalとfnで書け。

基本データ型と構造データ型 int, real, bool, stringなどの 「基本データ型」だけでは 複雑なデータを表現できない ⇒ 基本データ型を合成した 「構造データ型」を利用する 「XおよびY」のような「組み合わせ」を表すレコード型(C言語の構造体に相当) 「XまたはY」のような「場合わけ」を 表すバリアント型(C言語の共用体にほぼ相当)

レコードとレコード型 「レコード」:1つ以上の値にラベルをつけて組み合わせた値 「レコード型」:レコードの型(1つ以上の型にラベルをつけて組み合わせた型) 組み合わせる値や型の順序は影響しない - val r = { surname = "Sumii", = given = "Eijiro", age = 20 } ; val r = {age=20,given="Eijiro",surname="Sumii"} : {age:int, given:string, surname:string} - #age r ; val it = 20 : int

構文 レコード { ラベル1 = 式1, ..., ラベルn = 式n } レコード型 フィールドの取り出し #ラベル 式 「フィールド」:ラベルをつけてレコードとして組み合わされた値

課題4. 2 先の例のように、自分の苗字と名前と年齢を組み合わせて、レコードとして表せ。 そのレコードからフィールドgivenとsurnameを取り出し、文字列連結の二項演算子^を用いて、 "Eijiro Sumii" のように「名前スペース苗字」という形の文字列を作る、という式を書け。

ちょっと微妙な注意… SMLでは、たとえば先の例のようなレコードxから、 フィールドageを取り出す関数fを定義しようとすると、 - fun f x = #age x ; stdIn:17.1-17.17 Error: unresolved flex record (can't tell what fields there are besides #age) というエラーになる。このような場合は - fun f (x : {surname:string,given:string,age:int}) = = #age x ; val f = fn : {age:int, given:string, surname:string} -> int のようにxの型を指定しなければならない。 ちなみにOCamlでは、レコードやレコード型はあらかじめ定義する必要があるので、上述のような問題はない。

余談 SMLを拡張したSML#という言語には、 「レコード多相」(record polymorphism) という機能があり、前述のような問題はない。 (http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/) eiw01 % smlsharp SML# 0.30 (2007-07-03 16:16:12 JST) # fun f x = #age x ; val f = fn : ['a,'b#{age:'a}.'b -> 'a] # f { surname = "Sumii", given = "Eijiro", > age = 20 } ; val it = 20 : int

バリアントとバリアント型 「バリアント」:いくつかの値のうち、いずれか一つをとるような値 「バリアント型」:バリアントの型 どの一つであるか、「コンストラクタ」という名札(タグ)で区別する 「バリアント型」:バリアントの型

例1:曜日を表すバリアント - datatype day = = Sun | Mon | Tue | Wed | Thu = | Fri | Sat ; datatype day = Fri | Mon | Sat | Sun | Thu | Tue | Wed - Sun ; val it = Sun : day - Mon ; val it = Mon : day - Sat ; val it = Sat : day

datatype bool = true | false 例2:二者択一を表すバリアント - datatype binary = Yes | No ; datatype binary = No | Yes - Yes ; val it = Yes : binary - No ; val it = No : binary 注: bool型の値true, falseも datatype bool = true | false のようなバリアントとみなせる

例3:「整数またはエラー」を表すバリアント - datatype int_or_error = = Int of int | Error ; datatype int_or_error = Error | Int of int - Int 123 ; val it = Int 123 : int_or_error - Int 45 ; val it = Int 45 : int_or_error - Error ; val it = Error : int_or_error

例3:「整数またはエラー」を表すバリアント(続き) - fun my_div x y = = if y = 0 then Error else = Int (x div y) ; val my_div = fn : int -> int -> int_or_error - my_div 10 3 ; val it = Int 3 : int_or_error - my_div 10 0 ; val it = Error : int_or_error

例4:整数を葉とする木を表す バリアント - datatype itree = = ILeaf of int = | INode of { left : itree, = right : itree } ; datatype itree = ILeaf of int | INode of {left:itree, right:itree} - ILeaf 3 ; val it = ILeaf 3 : itree - INode { left = it, right = it } ; val it = INode {left=ILeaf 3,right=ILeaf 3} : itree - INode { left = it, right = ILeaf 7 } ; val it = INode {left=INode {left=ILeaf #,right=ILeaf #},right=ILeaf 7} : itree

構文 バリアント型の定義: datatype 型の名前 = コンストラクタ1 of 引数の型1 | コンストラクタ2 of 引数の型2 | ... | コンストラクタn of 引数の型n 引数をとらないコンストラクタは of以降を省略する

構文(続き) バリアント型の値を作る式: コンストラクタ 引数 関数適用と同じく並べて書く というか、SMLではコンストラクタも 関数の一種とみなされる 定義のときにof以降を省略した コンストラクタは引数をとらない

課題4. 3 my_divにならって、整数の割り算の 余りを求める関数my_modを書け。 除数が0のときはErrorを返すこと。 「浮動小数点数またはエラー」を表す バリアント型real_or_errorを定義し、 浮動小数点数の平方根を求める関数my_sqrtと、自然対数を求める関数my_lnを書け。引数が定義域外のときはErrorを返すこと。 文字列を葉とする木を表すバリアント型streeを定義し、木の例をいくつか作れ。

バリアントがどの値であるか という「場合わけ」 パターンマッチング バリアントがどの値であるか という「場合わけ」 例題:先の「曜日を表すバリアント」を受け取って、休日だったらtrue、平日だったらfalseを返す関数holidayを書け。

例題の解答 - fun holiday x = case x of = Sun => true | Mon => false = | Tue => false | Wed => false = | Thu => false | Fri => false = | Sat => true ; val holiday = fn : day -> bool - holiday Sun ; val it = true : bool - holiday Mon ; val it = false : bool - holiday Fri ; - holiday Sat ;

例題2 先の「整数を葉とする木」を表すバリアントを受け取り、すべての葉の整数の合計を返す関数isumを書け。

例題2の解答 - fun isum t = case t of = ILeaf i => i = | INode r => isum (#left r) + = isum (#right r) ; val isum = fn : itree -> int - isum (ILeaf 3) ; val it = 3 : int - isum (INode { left = ILeaf 3, = right = ILeaf 7 }) ; val it = 10 : int

構文 case 式 of コンストラクタ1 引数1 => 式1 | コンストラクタ2 引数2 => 式2 ... | コンストラクタn 引数n => 式n             ↑ コンストラクタが引数をとらない場合は省略

課題4. 4 先の「二者択一を表すバリアント」を受け取って、Yesに対してはNoを、Noに対してはYesを返す関数hinekureを書け。また、その関数の働きを実際に確かめよ。

課題4. 5 次の考え方に基づいて、先の「整数を葉とする木を表すバリアント」tを受け取って、その葉の数を返す関数sizeを書け。 tがILeaf iの形だったら1を返す tがINode rの形だったら、左の木の葉の数であるsize(#left r)と、右の木の葉の数であるsize(#right r)の和を返す

課題4. 6 (optional) 次の考え方に基づいて、先の「整数を葉とする木を表すバリアント」tを受け取って、その木の高さを返す関数heightを書け。 tがILeaf iの形だったら0を返す tがINode rの形だったら、左の木の高さと、右の木の高さのうち、より小さくないほうに1を加えて返す