- 日時 :2006/6/5 (Mon)
- 場所 :名大 理学部1号館(多元数理科学研究科) 309室
- 時刻 :18:00〜19:30
- 参加者:12名
- 話題 :
-- hoge
-- foo
-- bar
- GQFpyOxgKcLvFU -- [[tgiqdjh]] &new{2008-09-23 (火) 10:36:14};

#comment

----
#contents

* 5章 Exercise [#bfc2aa87]
**Exercise 1. 樋口 [#ge7486ac]
 1. [[]]  
 	'a list list   

 2. [[1;3]; ["hoge"]]
 	NG

 3. [3] :: []
 	int list list

 4. 2 :: [3] :: []
 	NG 
	 左からみてくと一見良さそうだけど,:: が右結合なので int list list に int をpush_frontしようとしている事になってしまう.
	 (2 :: [3]):: [] ならOK

 5. [] :: []
 	'a list list

 6. [(fun x -> x) ; (fun b -> not b) ]
 	(bool -> bool) list

**Exercise 2. 小笠原 [#g00c6393]
 (以下3行は前提とする関数)
 let hd (x :: rest) = x
 let tl (x :: rest) = rest
 let null = function [] -> true | _ ->  false

 ここから本題。 match を使わずにリスト操作しようとすると
 如何に大変かを体験してくださいという問題 :)
 let rec sum_list l =
   if null l then 0
   else (hd l) + (sum_list (tl l))

 let rec max_list l =
   if null (tl l) then hd l
   else
     let n1 = hd l
     and n2 = hd (tl l)
     and rest = tl (tl l) in
     if n1 > n2 then max_list (n1 :: rest)
     else max_list (n2 :: rest)

 n1,n2,rest のバインディングとか面倒そのもの。
 match を使えばもっと簡単。
 でも実はリスト以外の構造(キューとかスタックとか木とか)には
 先頭要素を取り出すパターンとかないので、
 やっぱり面倒なことを書かなくてはいけない罠.
 (リストが簡単になるだけでも効果絶大だけど)

**Exercise 3. 下村、山畑 [#j706ae3a]
***4 [#i203085e]


fold_leftを使ったもの。引数なしで定義すると…。
  let concat = List.fold_left (@) [];;
この時のコンパイラの出力。
  # val concat : '_a list list -> '_a list = <fun>
'_aに関しては第3回のページを参照。
これはOCamlの参照という機能を使えるようにするための制限だとか。
実際に引数を与えると型が固定される。
 # concat [[1;2];[3;4]];;
 - : int list = [1; 2; 3; 4]
 # concat;;
 - : int list list -> int list = <fun>
 # 

多相性を持たせるには引数を付ければよい。
  let concat list = List.fold_left (@) [] list;;
同じく、この時のコンパイラの出力。
  val concat : 'a list list -> 'a list = <fun>

***5 [#cc42e37c]
  let rec zip s1 s2 =
    match s1 with
        [] -> []
      | x::xs -> match s2 with
            [] -> []
          | y::ys -> (x,y) :: zip xs ys;;

matchに組を使うと見やすくなる。(括弧はいらないとのこと。)
  let rec zip' s1 s2 =
    match s1,s2 with
        [],_ -> []
      | _,[] -> []
      | x::xs,y::ys -> (x,y) :: zip' xs ys;;

***6-a [#za7320cc]
  let rec belong a s =
    match s with
        [] -> false
      | x::xs -> if x = a then true else belong a xs

***6-b [#j23b1206]
問題文をそのまま書いたもの。
  let rec intersect s1 s2 =
    match s1 with
        [] -> []
      | x::xs -> if belong x s2
        then x :: intersect xs s2
        else intersect xs s2;;

filterを使ったもの。
  let intersect' s1 s2 =
    filter (fun x -> belong x s1) s2;;

***6-c [#e0a93f70]
問題文をそのまま書いたもの。
  let rec union s1 s2 =
    match s1 with
        [] -> s2
      | x::xs -> if belong x s2
        then union xs s2
        else x :: (union xs s2);;

filterを使ったもの。
  let union' s1 s2 =
    s1 @ filter (fun x -> not (belong x s1)) s2;;

***6-d [#f1767059]
問題文をそのまま書いたもの。
  let rec diff s1 s2 =
    match s1 with
        [] -> []
      | x::xs -> if belong x s2
        then diff xs s2
        else x :: diff xs s2;;

filterを使ったもの。
  let diff' s1 s2 =
    filter (fun x -> not (belong x s2)) s1;;


**Exercise 5. よしひろ [#f105e7db]
 let forall' prop l = fold_right (&&) (map prop l) true
 let exists' prop l = fold_right (||) (map prop l) false
↑fold_rightとmapを使った方法。(問題にはfold_rightとmapを使えと書いてあった。)
しかしこれだとリストlを何度もみながら計算するので効率がいいとはいえない。
↓は小笠原さんによる改良versionである。(違ったら指摘してください。)
 let forall'' prop l = 
    fold_right (fun x b -> b && prop x) l true
 let exists'' prop l =
    fold_right (fun x b -> b || prop x) l false
 (OK です. 実用的には、fold_leftの方がいいかも. tail recursive だし. by小笠原)
トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS