* 予定のみ [#c00e6831] -日時 :2006/6/26 (Mon) -場所 :名大 理学部1号館(多元数理科学研究科) 307室 -時刻 :18:00〜19:30 -参加者:??名 #comment *Chapter 6. Exercise続き [#t10e4420] **Exercise 1 [#x1f19ca3] **Exercise 6 (小笠原) [#x9271744] **Exercise 7 [#vde22fdd] **Exercise 8 [#k7994cd4] **Exercise 9 (けいご) [#k464fb78] *Chapter 7. Exercise [#dc67177c] **Exercise 1 [#oe649801] ref型を type 'a ref = { mutable contents : 'a};; こんな定義の更新可能レコードと見て, 関数ref, 前置演算子!, 中置演算子:= をレコード操作で書け. -関数ref # let ref x = { contents = x } ;; val ref : 'a -> 'a ref = <fun> -前置演算子! # let ( ! ) x = x.contents ;; val ( ! ) : 'a ref -> 'a = <fun> -中置演算子:= # let ( := ) x y = x.contents <- y;; val ( := ) : 'a ref -> 'a -> unit = <fun> **Exercise 2 [#u76c0a17] 整数の参照をインクリメントする関数incr # let incr x = x := !x + 1;; val incr : int ref -> unit = <fun> **Exercise 3 [#fe92b783] # let f = ref (fun y -> y+1) let funny_fact x = if x = 1 then 1 else x * (!f(x-1));; # f := funny_fact;; # funny_fact 5;; let fは単に関数の参照が用意したいだけで,funで定義された関数の中身に意味は無い.(例えば let f = ref (fun y -> 1) でもOK)~ f := funny_factによりfがfunny_factをさすようになる.~ その結果,funny_factの定義中の!fが自分自身(funny_fact)を呼ぶ事になり,~ 階乗を素直に再帰的に定義した時と同じ形になっている. **Exercise 4 [#v6d2c968] # let fact_imp n = let i = ref n and res = ref 1 in while ( !i > 0 ) do res := !res * !i; i := !i - 1 done; !res;; val fact_imp : int -> int = <fun> **Exercise 5 [#q5984fe9] **Exercise 6 [#ke8a0983] **Exercise 7 [#n2c3331e] **Exercise 8 (末次) [#n6faefa9] まず元の定義 let rec change = function (_, 0) -> [] | ((c :: rest) as coins, total) -> if c > total then change (rest, total) else c :: change (coins, total - c) ;; これだと let us_coins = [25; 10; 5; 1] and gb_coins = [50; 20; 10; 5; 2; 1];; change (gb_coins, 43);; change (us_coins, 43);; は成功するが、 change ([5; 2], 16);; Exception: Match_failure ("", 66, -211). となって失敗する.これは大きい額から試していくので 5 で3回割ったあと、リストの最後 nil まで行って、 ([], 1) にマッチする規則が無いため. そこで失敗したら戻って小さな額で割るようにすればよい. let rec change = function (_, 0) -> [] | ((c :: rest) as coins, total) -> if c > total then change (rest, total) else (try c :: change (coins, total - c) with Failure "change" -> change (rest, total)) (* 失敗したら c で割るのを諦めて次に小さい数で続ける *) | _ -> raise (Failure "change");; (* ([], 1以上) のときは例外を投げる *) このようにすれば change ([5; 2], 16);; - : int list = [5; 5; 2; 2; 2] と計算できる.