module haskell_ch13 where -- for "Programming Haskell" chapter 13. open import Relation.Binary.PropositionalEquality open ≡-Reasoning open import Data.Empty import Level open import Relation.Nullary open import Relation.Binary.Core open import Data.List hiding (replicate; reverse; _++_; all; map; take; drop) open import Data.Nat open import Data.Bool data Nat : Set where Zero : Nat Succ : Nat → Nat add : Nat → Nat → Nat add Zero m = m add (Succ n) m = Succ (add n m) n+zero≡n : {n : Nat} → add n Zero ≡ n n+zero≡n {Zero} = refl n+zero≡n {Succ x} = begin add (Succ x) Zero ≡⟨ refl ⟩ --{ addの定義 } Succ (add x Zero) ≡⟨ cong (λ e → Succ e) (n+zero≡n {x}) ⟩ --{ 帰納法の仮定 } Succ x ∎ assoc-+ : {x y z : Nat} → add x (add y z) ≡ add (add x y) z assoc-+ {Zero} {y} {z} = begin add Zero (add y z) --{ addの定義 } ≡⟨ refl ⟩ add y z ≡⟨ sym refl ⟩ --{ addの定義(逆方向) } add (add Zero y) z ∎ assoc-+ {Succ x} {y} {z} = begin add (Succ x) (add y z) ≡⟨ refl ⟩ --{ addの定義 } Succ (add x (add y z)) ≡⟨ cong (λ e → Succ e) (assoc-+ {x}) ⟩ --{ 帰納法の仮定 } Succ (add (add x y) z) ≡⟨ sym refl ⟩ --{ addの定義(逆方向) } add (Succ (add x y)) z ≡⟨ sym refl ⟩ --{ addの定義(逆方向) } add (add (Succ x) y) z ∎ replicate : ∀{l}{A : Set l} → ℕ → A → List A replicate zero _ = [] replicate (suc n) c = c ∷ (replicate n c) replicate-length : ∀{l}{A : Set l} → {n : ℕ} → {c : A} → length (replicate n c) ≡ n replicate-length {A = A}{n = zero} {c} = begin length (replicate zero c) ≡⟨ refl ⟩ --{ replicateの定義 } zero ∎ replicate-length {n = suc x} {c} = begin length (replicate (suc x) c) ≡⟨ refl ⟩ --{ replicateの定義 } length (c ∷ (replicate x c)) ≡⟨ refl ⟩ --{ lengthの定義 } suc (length (replicate x c)) ≡⟨ cong (λ e → suc e) (replicate-length {n = x}) ⟩ --{ 帰納法の仮定 } suc x ∎ _++_ : ∀{l}{A : Set l} → (xs ys : List A) → List A [] ++ ys = ys (x ∷ xs) ++ ys = x ∷ (xs ++ ys) assoc-++ : ∀{l}{A : Set l} → {xs ys zs : List A} → (xs ++ ys) ++ zs ≡ xs ++ (ys ++ zs) assoc-++ {xs = []} {ys} {zs} = begin ([] ++ ys) ++ zs ≡⟨ refl ⟩ --{ ++の定義 } ys ++ zs ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } [] ++ (ys ++ zs) ∎ assoc-++ {xs = n ∷ ns} {ys} {zs} = begin ((n ∷ ns) ++ ys) ++ zs ≡⟨ refl ⟩ --{ ++の定義 } (n ∷ (ns ++ ys)) ++ zs ≡⟨ refl ⟩ --{ ++の定義 } n ∷ ((ns ++ ys) ++ zs) ≡⟨ cong (λ e → n ∷ e) (assoc-++ {xs = ns}) ⟩ --{ 帰納法の仮定 } n ∷ (ns ++ (ys ++ zs)) ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } (n ∷ ns) ++ (ys ++ zs) ∎ reverse : ∀{l}{A : Set l} → List A → List A reverse [] = [] reverse (x ∷ xs) = (reverse xs) ++ (x ∷ []) -- right identity rid-++ : ∀{l}{A : Set l} → {xs : List A} → xs ++ [] ≡ xs rid-++ {xs = []} = begin [] ++ [] ≡⟨ refl ⟩ --{ ++の定義 } [] ∎ rid-++ {xs = n ∷ ns} = begin (n ∷ ns) ++ [] ≡⟨ refl ⟩ --{ ++の定義 } n ∷ (ns ++ []) ≡⟨ cong (λ e → n ∷ e) (rid-++ {xs = ns}) ⟩ --{ 帰納法の定義 } n ∷ ns ∎ dist-rev : ∀{l}{A : Set l} → {xs ys : List A} → reverse (xs ++ ys) ≡ reverse ys ++ reverse xs dist-rev {xs = []} {ys} = begin reverse ([] ++ ys) ≡⟨ refl ⟩ --{ ++の定義 } reverse ys ≡⟨ sym rid-++ ⟩ --{ xs ++ [] ≡ xs } reverse (ys ++ []) ∎ dist-rev {xs = n ∷ ns} {ys} = begin reverse ((n ∷ ns) ++ ys) ≡⟨ refl ⟩ --{ ++の定義 } reverse (n ∷ (ns ++ ys)) ≡⟨ refl ⟩ --{ reverseの定義 } reverse (ns ++ ys) ++ (n ∷ []) ≡⟨ cong (λ e → e ++ (n ∷ [])) (dist-rev {xs = ns}) ⟩ --{ 帰納法の仮定 } (reverse ys ++ reverse ns) ++ (n ∷ []) ≡⟨ assoc-++ {xs = reverse ys} ⟩ --{ ++の結合律 } reverse ys ++ (reverse ns ++ (n ∷ [])) ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } reverse ys ++ reverse (n ∷ ns) ∎ eq-revrev : ∀{l}{A : Set l} → {xs : List A} → reverse (reverse xs) ≡ xs eq-revrev {xs = []} = begin reverse (reverse []) ≡⟨ refl ⟩ --{ reverseの定義 } reverse [] ≡⟨ refl ⟩ --{ reverseの定義 } [] ∎ eq-revrev {xs = n ∷ ns} = begin reverse (reverse (n ∷ ns)) ≡⟨ refl ⟩ --{ reverseの定義 } reverse ((reverse ns) ++ (n ∷ [])) ≡⟨ dist-rev {xs = reverse ns} ⟩ --{ reverseの分配律 } reverse (n ∷ []) ++ reverse (reverse ns) ≡⟨ cong (λ e → reverse (n ∷ []) ++ e) (eq-revrev {xs = ns}) ⟩ --{ 帰納法の仮定 } reverse (n ∷ []) ++ ns ≡⟨ refl ⟩ --{ reverseの定義 } (reverse [] ++ (n ∷ [])) ++ ns ≡⟨ refl ⟩ --{ reverseの定義 } ([] ++ (n ∷ [])) ++ ns ≡⟨ refl ⟩ --{ ++の定義 } (n ∷ []) ++ ns ≡⟨ refl ⟩ --{ ++の定義 } n ∷ ([] ++ ns) ≡⟨ refl ⟩ --{ ++の定義 } n ∷ ns ∎ reverse′ : ∀{l}{A : Set l} → List A → List A → List A reverse′ [] ys = ys reverse′ (x ∷ xs) ys = reverse′ xs (x ∷ ys) rev′≡rev : ∀{l}{A : Set l} → {xs ys : List A} → reverse′ xs ys ≡ (reverse xs) ++ ys rev′≡rev {xs = []} {ys} = begin reverse′ [] ys ≡⟨ refl ⟩ --{ reverse′の定義 } ys ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } [] ++ ys ≡⟨ sym refl ⟩ --{ reverseの定義(逆方向) } (reverse []) ++ ys ∎ rev′≡rev {xs = n ∷ ns} {ys} = begin reverse′ (n ∷ ns) ys ≡⟨ refl ⟩ --{ reverse′の定義 } reverse′ ns (n ∷ ys) ≡⟨ rev′≡rev {xs = ns} ⟩ --{ 帰納法の仮定 } (reverse ns) ++ (n ∷ ys) ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } (reverse ns) ++ ([] ++ (n ∷ ys)) ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } (reverse ns) ++ ((n ∷ []) ++ ys) ≡⟨ sym (assoc-++ {xs = reverse ns}) ⟩ --{ ++の結合律 } ((reverse ns) ++ (n ∷ [])) ++ ys ≡⟨ sym refl ⟩ --{ reverseの定義(逆方向) } (reverse (n ∷ ns)) ++ ys ∎ data Tree : Set where Leaf : ℕ → Tree Node : Tree → Tree → Tree flatten : Tree → List ℕ flatten (Leaf n) = n ∷ [] flatten (Node l r) = (flatten l) ++ (flatten r) flatten′ : Tree → List ℕ → List ℕ flatten′ (Leaf n) ns = n ∷ ns flatten′ (Node l r) ns = flatten′ l (flatten′ r ns) -- flatten′ t ns = (faltten t) ++ ns fla′≡fla : {t : Tree} → {ns : List ℕ} → flatten′ t ns ≡ (flatten t) ++ ns fla′≡fla {Leaf n} {ns} = begin flatten′ (Leaf n) ns ≡⟨ refl ⟩ --{ flatten′の定義 } n ∷ ns ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } [] ++ (n ∷ ns) ≡⟨ sym refl ⟩ --{ ++の定義(逆方向) } (n ∷ []) ++ ns ≡⟨ sym refl ⟩ --{ flattenの定義(逆方向) } (flatten (Leaf n)) ++ ns ∎ fla′≡fla {Node l r} {ns} = begin flatten′ (Node l r) ns ≡⟨ refl ⟩ --{ flatten′の定義 } flatten′ l (flatten′ r ns) ≡⟨ fla′≡fla {t = l} ⟩ --{ 帰納法の仮定 } (flatten l) ++ (flatten′ r ns) ≡⟨ cong (λ e → (flatten l) ++ e) (fla′≡fla {t = r}) ⟩ --{ 帰納法の仮定 } (flatten l) ++ ((flatten r) ++ ns) ≡⟨ sym (assoc-++ {xs = flatten l}) ⟩ --{ ++の結合律 } ((flatten l) ++ (flatten r)) ++ ns ≡⟨ sym refl ⟩ --{ flattenの定義(逆方向) } (flatten (Node l r)) ++ ns ∎ -- exercise 13.9 -- 1 重複のあるパターンで定義されている標準ライブラリ関数 -- min, max, toLower, toUpper, takeWhile, dropWhile, zip -- 2 succ-+ : {n m : Nat} → add n (Succ m) ≡ Succ (add n m) succ-+ {Zero} {m} = begin add Zero (Succ m) ≡⟨ refl ⟩ --{ addの定義 } Succ m ≡⟨ sym refl ⟩ --{ addの定義(逆方向) } Succ (add Zero m) ∎ succ-+ {Succ n} {m} = begin add (Succ n) (Succ m) ≡⟨ refl ⟩ --{ addの定義 } Succ (add n (Succ m)) ≡⟨ cong (λ e → Succ e) (succ-+ {n}) ⟩ --{ 帰納法の仮定 } Succ (Succ (add n m)) ≡⟨ refl ⟩ --{ addの定義 } Succ (add (Succ n) m) ∎ -- 3 comm-+ : {n m : Nat} → add n m ≡ add m n comm-+ {Zero} {m} = begin add Zero m ≡⟨ refl ⟩ --{ addの定義 } m ≡⟨ sym n+zero≡n ⟩ --{ add n Zero = n } add m Zero ∎ comm-+ {Succ n} {m} = begin add (Succ n) m ≡⟨ refl ⟩ --{ addの定義 } Succ (add n m) ≡⟨ cong (λ e → Succ e) (comm-+ {n}) ⟩ --{ 帰納法の仮定 } Succ (add m n) ≡⟨ sym refl ⟩ --{ addの定義(逆方向) } add (Succ m) n ≡⟨ cong (λ e → add e n) (sym (a+1≡succ-a {m})) ⟩ --{ add a (Succ Zero) = succ a } add (add m (Succ Zero)) n ≡⟨ sym (assoc-+ {m}) ⟩ --{ addの結合律 } add m (add (Succ Zero) n) ≡⟨ refl ⟩ --{ addの定義 } add m (Succ (add Zero n)) ≡⟨ refl ⟩ --{ addの定義 } add m (Succ n) ∎ where a+1≡succ-a : {a : Nat} → add a (Succ Zero) ≡ Succ a a+1≡succ-a {Zero} = begin add Zero (Succ Zero) ≡⟨ refl ⟩ --{ addの定義 } Succ Zero ∎ a+1≡succ-a {Succ a} = begin add (Succ a) (Succ Zero) ≡⟨ refl ⟩ --{ addの定義 } Succ (add a (Succ Zero)) ≡⟨ cong (λ e → Succ e) a+1≡succ-a ⟩ --{ 帰納法の仮定 } Succ (Succ a) ∎ {- 別解、問題2で示した add a (Succ b) ≡ Succ (add a b) を用いる。 add (Succ n) m ≡⟨ addの定義 ⟩ Succ (add n m) ≡⟨ 帰納法の仮定 ⟩ Succ (add m n) ≡⟨ 問題2 ⟩ add n (Succ m) ≡⟨ 問題2 ⟩ -} -- 4 all : ∀{l}{A : Set l} → (A → Bool) → List A → Bool all _ [] = true all p (x ∷ xs) = p x ∧ all p xs {-- replicate-eq : {n : ℕ} → ∀{l}{A : Set l} → {x : A} → all (== x) (replicate n x) ≡ true replicate-eq = {!!} 一般の型に対して == のような等式は定義できないため、Agdaでの証明は略する。 i) n = 0 のとき all (== x) (replicate zero x) ≡⟨ replicate の定義 ⟩ all (== x) [] ≡⟨ all の定義 ⟩ true ii) n = m + 1 のとき all (== x) (replicate (m + 1) x) ≡⟨ replicate の定義 ⟩ all (== x) (x ∷ (replicate m x)) ≡⟨ all の定義 ⟩ (x == x) ^ all (== x) (replicate m x) ≡⟨ == の反射律 ⟩ true ^ all (== x) (replicate m x) ≡⟨ ^ の定義 ⟩ all (== x) (replicate m x) ≡⟨ m に対する仮定 ⟩ true --} -- 5 すでに証明済み -- rid-++ -- assoc-++ -- 6 rev-lemma : ∀{l}{A : Set l} → {x : A} → {xs : List A} → reverse (xs ++ (x ∷ [])) ≡ x ∷ reverse xs rev-lemma {x = x} {xs = []} = begin reverse ([] ++ (x ∷ [])) ≡⟨ refl ⟩ --{ ++の定義 } reverse (x ∷ []) ≡⟨ refl ⟩ --{ reverseの定義 } reverse [] ++ (x ∷ []) ≡⟨ refl ⟩ --{ reverseの定義 } [] ++ (x ∷ []) ≡⟨ refl ⟩ --{ ++の定義 } x ∷ [] ≡⟨ sym refl ⟩ --{ reverseの定義(逆方向) } x ∷ reverse [] ∎ rev-lemma {x = x} {xs = n ∷ ns} = begin reverse ((n ∷ ns) ++ (x ∷ [])) ≡⟨ refl ⟩ --{ ++の定義 } reverse (n ∷ (ns ++ (x ∷ []))) ≡⟨ refl ⟩ --{ reverseの定義 } (reverse (ns ++ (x ∷ []))) ++ (n ∷ []) ≡⟨ cong (λ e → e ++ (n ∷ [])) (rev-lemma {xs = ns}) ⟩ --{ 帰納法の仮定 } (x ∷ reverse ns) ++ (n ∷ []) ≡⟨ refl ⟩ --{ ++の定義 } x ∷ (reverse ns ++ (n ∷ [])) ≡⟨ sym refl ⟩ --{ reverseの定義(逆方向) } x ∷ reverse (n ∷ ns) ∎ eq-revrev′ : ∀{l}{A : Set l} → {xs : List A} → reverse (reverse xs) ≡ xs eq-revrev′ {xs = []} = begin reverse (reverse []) ≡⟨ refl ⟩ --{ reverseの定義 } reverse [] ≡⟨ refl ⟩ --{ reverseの定義 } [] ∎ eq-revrev′ {xs = n ∷ ns} = begin reverse (reverse (n ∷ ns)) ≡⟨ refl ⟩ --{ reverseの定義 } reverse ((reverse ns) ++ (n ∷ [])) ≡⟨ rev-lemma {xs = reverse ns} ⟩ --{ reverse (xs ++ [x]) ≡ x ∷ reverse xs } n ∷ (reverse (reverse ns)) ≡⟨ cong (λ e → n ∷ e) (eq-revrev′ {xs = ns}) ⟩ --{ 帰納法の仮定 } n ∷ ns ∎ -- 7 map : ∀{l}{A B : Set l} → (f : A → B) → List A → List B map f [] = [] map f (x ∷ xs) = f x ∷ map f xs _∘_ : ∀{l}{A B C : Set l} → (f : B → C) → (g : A → B) → A → C (f ∘ g) x = f (g x) map-comp : ∀{l}{A B C : Set l} → {f : B → C} → {g : A → B} → {xs : List A} → map f (map g xs) ≡ map (f ∘ g) xs map-comp {f = f} {g} {xs = []} = begin map f (map g []) ≡⟨ refl ⟩ --{ mapの定義 } map f [] ≡⟨ refl ⟩ --{ mapの定義 } [] ≡⟨ sym refl ⟩ --{ mapの定義(逆方向) } map (f ∘ g) [] ∎ map-comp {f = f} {g} {xs = n ∷ ns} = begin map f (map g (n ∷ ns)) ≡⟨ refl ⟩ --{ mapの定義 } map f (g n ∷ map g ns) ≡⟨ refl ⟩ --{ mapの定義 } f (g n) ∷ map f (map g ns) ≡⟨ cong (λ e → f (g n) ∷ e) (map-comp {xs = ns}) ⟩ --{ 帰納法の仮定 } f (g n) ∷ map (f ∘ g) ns ≡⟨ sym refl ⟩ --{ ∘の定義(逆方向) } (f ∘ g) n ∷ map (f ∘ g) ns ≡⟨ sym refl ⟩ --{ mapの定義(逆方向) } map (f ∘ g) (n ∷ ns) ∎ -- 8 take : ∀{l}{A : Set l} → ℕ → List A → List A take zero _ = [] take (suc n) [] = [] take (suc n) (x ∷ xs) = x ∷ (take n xs) drop : ∀{l}{A : Set l} → ℕ → List A → List A drop zero xs = xs drop (suc n) [] = [] drop (suc n) (x ∷ xs) = drop n xs take-drop : ∀{l}{A : Set l} → {n : ℕ} → {xs : List A} → take n xs ++ drop n xs ≡ xs take-drop {n = zero} {xs = []} = begin take zero [] ++ drop zero [] ≡⟨ refl ⟩ --{ takeの定義 } [] ++ drop zero [] ≡⟨ refl ⟩ --{ dropの定義 } drop zero [] ≡⟨ refl ⟩ [] ∎ take-drop {n = zero} {xs = x ∷ xs} = begin take zero (x ∷ xs) ++ drop zero (x ∷ xs) ≡⟨ refl ⟩ --{ takeの定義 } [] ++ drop zero (x ∷ xs) ≡⟨ refl ⟩ --{ ++の定義 } drop zero (x ∷ xs) ≡⟨ refl ⟩ --{ dropの定義 } x ∷ xs ∎ take-drop {n = suc n} {xs = []} = begin take (suc n) [] ++ drop (suc n) [] ≡⟨ refl ⟩ --{ takeの定義 } [] ++ drop (suc n) [] ≡⟨ refl ⟩ --{ ++の定義 } drop (suc n) [] ≡⟨ refl ⟩ --{ dropの定義 } [] ∎ take-drop {n = suc n} {xs = x ∷ xs} = begin take (suc n) (x ∷ xs) ++ drop (suc n) (x ∷ xs) ≡⟨ refl ⟩ --{ takeの定義 } (x ∷ take n xs) ++ drop (suc n) (x ∷ xs) ≡⟨ refl ⟩ --{ ++の定義 } x ∷ (take n xs ++ drop (suc n) (x ∷ xs)) ≡⟨ refl ⟩ --{ dropの定義 } x ∷ (take n xs ++ drop n xs) ≡⟨ cong (λ e → x ∷ e) (take-drop {n = n} {xs = xs}) ⟩ --{ 帰納法の仮定 } x ∷ xs ∎ -- 9 -- ***** 整数順序の定義、定理 *************************** -- data _<=_ : Rel Nat Level.zero where z<=n : {n : Nat} → Zero <= n s<=s : {m n : Nat} (m<=n : m <= n) → Succ m <= Succ n eq→<= : {x y : Nat} → x ≡ y → x <= y eq→<= {Zero} {Zero} refl = z<=n eq→<= {Zero} {Succ y} () eq→<= {Succ x} {Zero} () eq→<= {Succ x} {Succ y} suc-x≡suc-y = s<=s (eq→<= x≡y) where ≡-suc : {a b : Nat} → Succ a ≡ Succ b → a ≡ b ≡-suc refl = refl x≡y : x ≡ y x≡y = ≡-suc suc-x≡suc-y <=trans : {x y z : Nat} → x <= y → y <= z → x <= z <=trans {Zero} {_} {z} x<=y y<=z = z<=n <=trans {Succ x}{Zero} {z} () <=trans {Succ x}{Succ y}{Zero} suc-x<=suc-y () <=trans {Succ x}{Succ y}{Succ z} (s<=s x<=y) (s<=s y<=z) = s<=s (<=trans x<=y y<=z) <=+n : {a b : Nat} → a <= add a b <=+n {Zero} = z<=n <=+n {Succ a} = s<=s (<=+n {a}) a+c<=b+d : {a b c d : Nat} → a <= b → c <= d → add a c <= add b d a+c<=b+d {Zero} {b} {c} {d} z<=n c<=d = <=trans p1 p2 where p1 : c <= add d b p1 = <=trans (c<=d) (<=+n) p2 : add d b <= add b d p2 = eq→<= (comm-+ {d}) a+c<=b+d {Succ a}{Zero} () a+c<=b+d {Succ a}{Succ b}{Zero} {d} (s<=s a<=b) z<=n = s<=s (<=trans p2 p1) where p1 : a <= add b d p1 = <=trans a<=b <=+n p2 : add a Zero <= a p2 = eq→<= n+zero≡n a+c<=b+d {Succ a}{Succ b}{Succ c}{Zero} _ () a+c<=b+d {Succ a}{Succ b}{Succ c}{Succ d} (s<=s a<=b) (s<=s c<=d) = s<=s p4 where p1 : add a c <= add b d p1 = a+c<=b+d a<=b c<=d p2 : add a (Succ c) <= Succ (add a c) p2 = eq→<= (succ-+ {a}) p3 : Succ (add b d) <= add b (Succ d) p3 = eq→<= (sym (succ-+ {b})) p4 : add a (Succ c) <= add b (Succ d) p4 = <=trans p2 (<=trans (s<=s p1) p3) -- ****************************************************** -- cnt-leaf : Tree → Nat cnt-leaf (Leaf _) = Succ Zero cnt-leaf (Node l r) = add (cnt-leaf l) (cnt-leaf r) cnt-node : Tree → Nat cnt-node (Leaf _) = Zero cnt-node (Node l r) = Succ (add (cnt-node l) (cnt-node r)) tree-lemm : {t : Tree} → Succ (cnt-node t) <= cnt-leaf t tree-lemm {Leaf n} = eq→<= p where p : Succ (cnt-node (Leaf n)) ≡ cnt-leaf (Leaf n) p = begin Succ (cnt-node (Leaf n)) ≡⟨ refl ⟩ --{ cnt-nodeの定義 } Succ Zero ≡⟨ sym refl ⟩ --{ cnt-leafの定義(逆方向) } cnt-leaf (Leaf n) ∎ tree-lemm {Node l r} = <=trans p4 p3 where for-l : Succ (cnt-node l) <= cnt-leaf l for-l = tree-lemm {l} for-r : Succ (cnt-node r) <= cnt-leaf r for-r = tree-lemm {r} p1 : add (Succ (cnt-node l)) (Succ (cnt-node r)) <= add (cnt-leaf l) (cnt-leaf r) p1 = a+c<=b+d for-l for-r p2 : add (Succ (cnt-node l)) (Succ (cnt-node r)) ≡ Succ (add (Succ (cnt-node l)) (cnt-node r)) p2 = succ-+ {(Succ (cnt-node l))} p3 : Succ (add (Succ (cnt-node l)) (cnt-node r)) <= add (cnt-leaf l) (cnt-leaf r) p3 = <=trans (eq→<= (sym p2)) p1 p4 : Succ (cnt-node (Node l r)) <= Succ (add (Succ (cnt-node l)) (cnt-node r)) p4 = eq→<= refl -- 10 -- 省略