13.9 練習問題
- 以下の定義が与えられているとする。
map f [] = [] map f (x:xs) = f x : map f xs (f.g) x = f (g x)map f (map g xs) = map (f.g) xs
であることを、xsに対する数学的帰納法で証明せよ。
xs = []
の場合左辺 = map f (map g []) = map f [] = [] 右辺 = map (f.g) [] = []
xs = ns
のときに式が成り立つと仮定して、xs = n:ns
の場合左辺 = map f (map g (n:ns)) = map f (g n : map g ns) = f (g n) : map f (map g ns) = (f.g) n : map (f.g) ns 右辺 = map (f.g) (n:ns) = (f.g) n : map (f.g) ns
n = 0
の場合左辺 = take 0 xs ++ drop 0 xs = [] ++ xs = xs = 右辺
n > 0, xs = []
の場合左辺 = take n [] ++ drop n [] = [] ++ [] = [] = 右辺
n = m, xs = ys
で式が成り立つと仮定して、n = m+1, xs = y:ys
の場合左辺 = take (m+1) (y:ys) ++ drop (m+1) (y:ys) = (y: take m ys) ++ (drop m ys) = y : (take m ys ++ drop m ys) = y:ys = 右辺
ヒント通り、木の葉と節の個数を数える関数を定義する。
countLeaf :: Tree -> Int countLeaf Leaf _ = 1 countLeaf Node l r = countLeaf l + countLeaf r countNode :: Tree -> Int countNode Leaf _ = 0 countNode Node l r = 1 + countNode l + countNode r
その上で、countLeaf t = countNode t + 1
が常に成り立つことをを証明する。
t = Leaf n
の場合左辺 = countLeaf Leaf n = 1 右辺 = countNode Leaf n + 1 = 0 + 1 = 1
t = l
およびt = r
で式が成り立つと仮定してt = Node l r
の場合左辺 = countLeaf Node l r = countLeaf l + countLeaf r = (countNode l + 1) + (countNode r + 1) = 2 + countNode l + countNode r 右辺 = countNode Node l r + 1 = 1 + countNode l + countNode r + 1 = 2 + countNode l + countNode r
comp
の定義を再掲しておく。
comp :: Expr -> Code comp (Val n) = [Push n] comp (Add x y) = comp x ++ comp y ++ [ADD]
e = Val n
の場合comp' (Val n) c = [Push n] ++ c = Push n : c
e = x
およびe = y
でcomp' e c = comp e ++ c
が成り立つと仮定してe = Add x y
の場合comp' (Add x y) c = comp x ++ comp y ++ [ADD] ++ c = comp' x (comp y ++ [ADD] ++ c) = comp' x (comp' y (ADD : c))
まとめると
comp' :: Expr -> Code -> Code comp' (Val n) c = Push n : c comp' (Add x y) c = comp' x (comp' y (ADD : c))
ついに終わった……