脱関数化を実用する B - shiatsumat/fp-papers GitHub Wiki

[§5.3.2](脱関数化を実用する 5#section5-3-2) で与えられた正当性の判断基準を証明するために、

  • P1(r,s,k) ≜ accept (r, s, k) ~> TruesL(r)L(k)
  • P2(k,s) ≜ pop_and_accept (k, s) ~> TruesL(r)L(k)
  • P3(r,s,k) ≜ accept_star (r, s, k) ~> TruesL(r)L(k)

とし、相互整礎帰納法によってそれぞれの命題に尺度を与え、どの場合の証明も真に小さい命題にのみ依存するようにする。この命題の尺度は自然数の組として与えられ、辞書順で並べられる。

  • |P1(r,s,k)| = (|s|, |r||s| + |k||s|)

  • |P2(k,s)| = (|s|, |k||s|)

  • |P3(r,s,k)| = (|s|, |r||s| ( 3|s| + 2 ) + |k||s|)

    • ただし |s| は s の要素数である。
  • |Zero|n = 1

  • |One|n = 1

  • |Char c|n = 1

  • |Sum r1 r2|n = |r1|n + |r2|n

  • |Cat r1 r2|n = |r1|n + |r2|n + 2

  • |Star r|n = ( 3n + 2 ) |r|n

  • |Empty|n = 0

  • |Accept r k|n = |r|n + |k|n + 1

  • |AcceptStar s r k|n = |r|min( 3(n+1), 3|s| ) + |k|n

それぞれの場合についての証明は以下の通りである。

P1(r,s,k)》

(i) r = Zero のとき

accept (r, s, k) ~> TruesL(Zero)L(k) = ∅ も成り立たないので、同値は成り立つ。

(ii) r = One のとき

accept (r, s, k) ~> Truepop_and_accept (k, s) ~> True と同値である。整礎帰納法の仮定より、pop_and_accept (k, s) ~> TruesL(k) と同値であり、L(One) = {[]} であるので、sL(One)L(k) である。

(iii) r = Char c のとき

accept (r, s, k) ~> Trues = c : s' かつ pop_and_accept (k, s') ~> True であることと同値である。その場合、|s'| < |s| かつ |P2(k,s')| < |P1(Char c,s,k)| である。帰納法の仮定より s'L(k) であるので、s = [c] ++ s'L(Char c)L(k) である。

(iv) r = Sum r1 r2 のとき

accept (r, s, k) ~> Trueaccept (r1, s, k) ~> True または accept (r2, s, k) ~> True であることと同値である。|r|n は常に正であるので、両方とも「より小さい」から、帰納法の仮定より sL(r1)L(k) または sL(r2)L(k) であることと同値であると分かる。さらにこれは s ∈ (L(r1)L(k)) ∪ (L(r2)L(k)) = (L(r1)∪L(r2))L(k) = L(r)L(k) と同じである。

(v) r = Cat r1 r2 のとき

accept (r, s, k) ~> Trueaccept (r1, s, Accept r2 k) ~> True と同値である。

順序のより小さい P1(r1,s,Accept r2 k) により、これが sL(r1)L(Accept r2 k) = L(r1)L(r2)L(k) = L(r)L(k) と同値であると分かる。

(vi) r = Star r1 のとき

accept (r, s, k) ~> Trueaccept_star (r1, s, k) ~> True と同値であると分かる。ゆえに、代わりにただ P3(r1,s,k) を証明すればよい。

accept_star (r1, s, k) ~> Truepop_and_accept (k, s) ~> True または accept (r1, s, AcceptStar s r1 k) ~> True であることと同値である。

前者の場合は sL(k) ⊂ L(k)L(k) と同値である。これは P2(k,s) が「より小さい」ので、帰納法の仮定より言える。

後者の場合は sL(r1)L(AcceptStar s r1 k) = L(r1) ( (L(r1)L(k)) ∖ {s} ) と同値である。これも帰納法の仮定より言える。

集合に対する基本演算を使うことで、これら2つの述語の論理和を取るのは、s が和集合に入っているということと同値である。つまり言い換えると、s ∈ (L(r1)0 ∪ (L(r1) ∖ {[]})L(r1))L(k) = L(r1)L(k) である。

ただし、P3(r1,s,k) は P1(Star r1,s,k) より真に小さくはないが、ここでは P3(r1,s,k) を仮定していないので問題ない。

P2(k,s)》

(i) k = Empty のとき

sL(k) であり、これは s が空文字列であることと同値であり、まさにこのとき pop_and_accept (k, s) ~> True が成り立つ。

(ii) k = Accept r k' のとき

sL(k) = L(r)L(k') であり、これは帰納法の仮定より accept (r, s, k') ~> True と同値である。(P1(r,s,k') は P2(Accept r k',s) よりも 1 だけ小さい。)この場合、pop_and_accept (k, s)accept (r, s, k') ~> True である。

(iii) k = AcceptStar s' r k' のとき

sL(k) は ss' かつ sL(r)L(k') であることと同値である。帰納法の仮定より、sL(r)L(k') は accept_star (r, s, k) ~> True と同値であり、不等式は Haskell のプログラムに反映されているので、s /= s' ~> True である。これらを合わせると、sL(k) が成立することは pop_and_accept (k, s) が成立することと同値である。

P3(r,s,k)》

この場合は P1(Star r.s,k) の中の部分帰納法と同様に証明される。実際、|P3(r,s,k)| = |P1(Star r.s,k)| である。

(証明終わり)
⚠️ **GitHub.com Fallback** ⚠️