第3章 練習問題 6-10
6 状態不変表明
P(R,Ys) = (Reverse(Xs) = R + Reverse(Ys))
ただし、ここで+はAppendを表す。
証明は必要かどうかわからないから、省略で。
8 反復的append
fun {Append Xs Ys} fun {Reverse R Xs} case Xs of nil then R [] X|Xr then {Reverse X|R Xr} end end fun {ReverseAppend R Xs} case Xs of nil then R [] X|Xr then {ReverseAppend X|R Xr} end end in {Reverse nil {ReverseAppend {Reverse nil Xs} Ys}} end
9 反復計算とデータフロー変数
実際にデータフロー変数を使わずに、appendを定義することができた。
10 あるものがリストであるかどうかをチェックすること
変更すると{Leaf [1 2 3]}のようにリストを引数として与えるとブロックする。
2.8.2節において
内包チェック
== (および、その逆の反駁チェック \= )は二引数の関数で、 と の等・不等が分かるまでブロックする。内包チェックも反駁チェックも束縛は行なわない。
とある。
そのため、X \= _|_はXがリストの場合、_|_の内容が分かるまでブロックする。次のように書きなおすとこのことがはっきりする。
fun {Leaf2 L} X Xr in % XとXrが分かるまでブロックする L == X|Xr end
11 差分リストの限界
ここで問題といわれているのは、
local X Y Z in local D1 = (1|2|3|X)#X D2 = (4|5|6|Y)#Y D3 = (7|8|9|Z)#Z in {Show {AppendD D1 D2}} % (1) {Show {AppendD D1 D3}} end end
という状況。
ここで、一度目のAppendD終了後(1の位置)でD1は(1|2|3|4|5|6|Y)#(4|5|6|Y)に束縛されている。
これを二度目のAppendDに渡すと、4|5|6|Yを7|8|9|Zで束縛しようとする。そのためエラーが発生する。
12 リストの平坦化の計算量
分からない。nとkが両方パラメータで、どう漸化式を解いたらいいか分からない。
直感によるとFlattenはO(n*n)でFlattenDはO(n)。
13 行列操作
転置と積だけ。
fun {Trans M} fun {Split Xs} case Xs of (Y|Yr)|Xr then Hs#Ts = {Split Xr} in (Y|Hs)#(Yr|Ts) else nil#nil end end fun {Join Ys Xs} case Ys#Xs of (Y|Yr)#(X|Xr) then (Y|X)|{Join Yr Xr} else nil end end in case M of nil then nil [] [[X]] then [[X]] [] (X|Xr)|Ys then Y#Yr = {Split Ys} in (X|Y)|{Join Xr {Trans Yr}} end end fun {Mul M1 M2} fun {Product Xs Ys} case Xs#Ys of (X|Xr)#(Y|Yr) then (X*Y)+{Product Xr Yr} else 0 end end M3 = {Trans M2} in {Map M1 fun {$ X} {Map M3 fun {$ Y} {Product X Y} end} end} end
14 FIFOキュー
(a)
Xが未束縛のままになる。
(b)
キューに何かが挿入されている場合、SとEの等価性を判定するにはSとEが共に束縛されていなければならない。
しかし、Eは常に自由なので、ブロックしてしまう。
15 クイックソート
fun {QSort Xs} proc {QSortD Xs ?Y1 Y} case Xs of nil then Y1 = Y [] X|Xr then L1 = {Filter Xr fun {$ V} V < X end} L2 = {Filter Xr fun {$ V} V >= X end} Z in {QSortD L1 Y1 X|Z} {QSortD L2 Z Y} end end Y1 in {QSortD Xs Y1 nil} Y1 end
16 末尾再帰の畳み込み
fun {Zip Xs Ys} fun {Iter Xs Zs} case Xs of nil then Zs = Ys nil [] X|Xr then Z in (X#Z)|{Iter Xr Z|Zs} end end in {Iter Xs nil} end
(X#Z)|{Iter ...}は核言語に変換するときに、末尾再帰になるはず。
ヒントを正しく活用していない気がするが、単一化の特徴を使っているし、問題ないはず。
17 カリー化
gumpの使い方を調べるのが大変なので、後回し。