def s:_->nat->nat|(m+1)(n+1):=(n+1)*(s m n+s m(n+1))|0 0:=1|_ _:=0
オンラインでお試しください!
正当性の証明
オンラインでお試しください!
説明
関数をungolfしましょう:
def s : nat->nat->nat
| (m+1) (n+1) := (n+1)*(s m n + s m (n+1))
| 0 0 := 1
| _ _ := 0
この関数は、パターンマッチングと再帰によって定義されます。どちらにも組み込みのサポートがあります。
s(m+1, n+1) = (n+1) * (s(m, n) + s(m, n+1)
and を定義しますs(0, 0) = 1
。これは、開いたままにs(m+1, 0)
しますs(0, n+1)
。どちらも0
、最後のケースまでに定義されています。
リーンはlamdba微積分構文を使用するため、s m n
ですs(m, n)
。
さて、正しさの証拠:私は2つの方法でそれを述べました:
def correctness : ∀ m n, fin (s m n) ≃ { f : fin m → fin n // function.surjective f } :=
λ m, nat.rec_on m (λ n, nat.cases_on n s_zero_zero (λ n, s_zero_succ n)) $
λ m ih n, nat.cases_on n (s_succ_zero m) $ λ n,
calc fin (s (nat.succ m) (nat.succ n))
≃ (fin (n + 1) × (fin (s m n + s m (n + 1)))) :
(fin_prod _ _).symm
... ≃ (fin (n + 1) × (fin (s m n) ⊕ fin (s m (n + 1)))) :
equiv.prod_congr (equiv.refl _) (fin_sum _ _).symm
... ≃ (fin (n + 1) × ({f : fin m → fin n // function.surjective f} ⊕
{f : fin m → fin (n + 1) // function.surjective f})) :
equiv.prod_congr (equiv.refl _) (equiv.sum_congr (ih n) (ih (n + 1)))
... ≃ {f // function.surjective f} : s_aux m n
def correctness_2 (m n : nat) : s m n = fintype.card { f : fin m → fin n // function.surjective f } :=
by rw fintype.of_equiv_card (correctness m n); simp
間に全単射:最初のものは本当に何が起こっているかである[0 ... s(m, n)-1]
とのsurjections [0 ... m-1]
へ[0 ... n-1]
。
もう一つは、通常、その、記載されている方法ですs(m, n)
からsurjectionsのカーディナリティです[0 ... m-1]
へ[0 ... n-1]
。
リーンは、(集合論の代わりに)型理論を基礎として使用します。型理論では、すべてのオブジェクトに固有の型があります。nat
は自然数のタイプであり、自然数であるステートメント0
はと表され0 : nat
ます。私たちはそれ0
がタイプnat
であり、それnat
が持っていると言います0
住民としてているます。
命題(ステートメント/アサーション)もタイプです:それらの住民は命題の証拠です。
def
:定義を導入します(全単射は、単なる命題ではなく実際に機能であるため)。
correctness
:定義の名前
∀ m n
:for m
およびn
(Leanはnat
、次の理由により、タイプがであると自動的に推測します)
fin (s m n)
は、より小さい自然数のタイプですs m n
。住民を作るために、自然数とそれがより小さいことの証明を提供しますs m n
。
A ≃ B
:タイプA
とタイプの間の全単射B
。実際には逆関数を提供する必要があるため、全単射と言うのは誤解を招きます。
{ f : fin m → fin n // function.surjective f }
surjectionsのタイプfin m
にfin n
。この構文は、タイプfin m → fin n
、つまりからの関数のタイプからサブタイプを構築fin m
しfin n
ます。構文は{ var : base type // proposition about var }
です。
λ m
:∀ var, proposition / type involving var
は実際にはvar
入力として受け取る関数なのでλ m
、入力を導入します。∀ m n,
の略記です∀ m, ∀ n,
nat.rec_on m
:で再帰を行いm
ます。のために何かを定義するにはm
、のためにモノを定義してからのためにモノを0
与えk
、ためにモノをビルドしk+1
ます。これは帰納法に似ており、実際、これは教会とハワードの通信の結果であることに気付くでしょう。構文はnat.rec_on var (thing when var is 0) (for all k, given "thing when k is k", build thing when var is "k+1")
です。
ねえ、これは長くなっていて、私は3行目ですcorrectness
...