6.5 リスト処理の一般構造と汎用のリスト処理関数
問 6.8
以下の各関数が行う処理に関して上記の分析を行い,対応するとを MLの式として定義せよ.
-
•
map
-
•
@
-
•
flatten
-
•
filter
-
•
permutations
解答例
-
•
map
リストがnilの時はnil、 リストが :: の形なら, 部分リストに対する値を計算すると、 は、にをmapした結果であるから、 全体の結果はf h :: である。 従って、、 である。 -
•
@
第一要素L1でfoldする。 L1がnilの時は第2要素L2、 L1が :: の形なら, はtとL2の連結結果のはずであるから、 全体の結果はh :: である。 従って、 、 である。 -
•
flatten L
リストがnilの時はnil、 リストが :: の形なら, 部分リストに対する値を計算すると、 はリスト、はをflattenした結果のはずであるから、 全体の結果はh @ である。 従って、、 である。 -
•
filter P L
リストがnilの時はnil、 リストが :: の形なら, 部分リストに対する値を計算すると、 はをfilterした結果のはずであるから、 全体の結果は、もし hがtrueならh @ 、folseならである。 従って、、 である。 -
•
permutations
リストがnilの時は[nil]、 リストが :: の形なら, 部分リストに対する値を計算すると、 はをpermutationした結果のはずであるから、 全体の結果は、の各要素に対して、その可能な位置にを挿入したリストすべてである。 従って、、 である。
問 6.9
以下のリスト処理関数を foldr を使って定義せよ.
-
1.
map, flatten, member, unique, prefixList, permutations の各関数.
-
2.
リストと 条件(bool型の関数) を受け取り,リストの中に条件を満たす要素が存在するか否か判定する関数 existsおよび, リストの中のすべての要素が条件を満たすか判定する関数 forall. 定義上,任意の条件関数に対して,exists nil は false,forall nil は true を返すことに注意せよ.
-
3.
整数リストのプレフィックス和を求める関数 prefixSum. ただし,整数リストのプレフィックス和 はである.
解答例
fun map f L = foldr (fn (h,R) => f h :: R) nil L fun flatten L = foldr (fn (h,R) => h @ R) nil L fun member e L = foldr (fn (h,R) => R orelse e = h) false L fun unique L = foldr (fn (h,R) => if member h R then R else h :: R) nil L fun prefixList L = foldr (fn (x,l)=> [x]::(map (fn y => x::y) l)) nil L; fun permutations L = let fun insertAll s nil = [[s]] | insertAll s (h::t) = let val L = insertAll s t in (s::(h::t)) :: (map (fn x => h::x) L) end in foldr (fn (x,y) => foldr (fn (a,b) => insertAll x a @ b) nil y) [nil] L end fun exists p L = foldr (fn (y,r) => p y orelse r) false L fun forall p L = foldr (fn (y,r) => p y andalso r) true L fun prefixSum L = foldr (fn (x,y) => x::(map (fn z => z + x) y)) nil L
問 6.10
foldr の処理は,以下のような等式の結果を求めることと理解できる.
これに対して,以下のような動作をする foldl もトップレベルで定義されている.
-
1.
foldl の定義を与えよ.
-
2.
foldl を使って rev を定義せよ.
解答例
fun foldl f z nil = z | foldl f z (h::t) = foldl f (f (h,z)) t fun rev L = foldl (op ::) nil L
問 6.11
関係のリスト表現で,同一の要素が一回しか含まれないとき,正規形と呼ぶ ことにする. 上で定義した tc は,入力が正規形であっても結果は正規形とは限ら ない.
-
1.
tc が正規形とならない正規形のリストの例を挙げよ.
-
2.
正規形の入力に対しては,必ず正規形の結果を返すように,tc の定 義を修正せよ.
解答例 正規形の入力に対して、tc が正規形にならない例: tc [(1,1),(1,2),(2,3)]。
正規形を維持するためのtcの改良:簡単な解決法は、
fun normalTc R = unique (tc R)
問 6.12
関係のリスト表現に関する以下の関数を定義せよ.
-
1.
関係と組に対して,か否かを判定する関数 isRelated.
-
2.
関係と点に対して,集合を求める関数 targetOf.
-
3.
関係と点に対して,集合を求める関数 sourceOf.
-
4.
関係の逆を求める関数 inverseRel.
解答例
fun isRelated (R,a) = member a R fun targetOf (R,a) = filter (fn (x,y) => x = a) R fun sourceOf (R,a) = filter (fn (x,y) => y = a) R fun inverseRel R = map (fn (a,b) => (b, a)) R