From e1d2ae8c967e5839c767ac7f003a03a33bbce389 Mon Sep 17 00:00:00 2001 From: s-taiga <56785231+s-taiga@users.noreply.github.com> Date: Wed, 4 Sep 2024 19:13:33 +0900 Subject: [PATCH] =?UTF-8?q?10.5=E7=AB=A0=20fin=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 翻訳開始 * 翻訳完了 --- functional-programming-lean/src/SUMMARY.md | 2 +- .../src/programs-proofs/fin.md | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/functional-programming-lean/src/SUMMARY.md b/functional-programming-lean/src/SUMMARY.md index e0ceb157..4ffa3759 100644 --- a/functional-programming-lean/src/SUMMARY.md +++ b/functional-programming-lean/src/SUMMARY.md @@ -65,7 +65,7 @@ - [同値の証明](programs-proofs/tail-recursion-proofs.md) - [配列と関数の停止](programs-proofs/arrays-termination.md) - [その他の不等式](programs-proofs/inequalities.md) - - [Safe Array Indices](programs-proofs/fin.md) + - [安全な配列のインデックス](programs-proofs/fin.md) - [Insertion Sort and Array Mutation](programs-proofs/insertion-sort.md) - [Special Types](programs-proofs/special-types.md) - [Summary](programs-proofs/summary.md) diff --git a/functional-programming-lean/src/programs-proofs/fin.md b/functional-programming-lean/src/programs-proofs/fin.md index 9968c408..61e92e1c 100644 --- a/functional-programming-lean/src/programs-proofs/fin.md +++ b/functional-programming-lean/src/programs-proofs/fin.md @@ -1,49 +1,99 @@ + +# 安全な配列のインデックス + + + +`Array` と `Nat` についての `GetElem` インスタンスは与えられた `Nat` が配列よりも小さいことの証明を要求します。実際には、これらの証明はインデックスと一緒に関数に渡されることが多いです。インデックスと証明を別々に渡すのではなく、`Fin` という型を使うことで、インデックスと証明を1つの値にまとめることができます。これによりコードはさらに読みやすくなります。さらに、配列に対する組み込み操作の多くは、インデックスの引数を `Nat` ではなく `Fin` として受け取るため、これらの組み込み操作を使用するには `Fin` の使い方を理解する必要があります。 + + +型 `Fin n` は `n` 未満の数を表します。つまり、`Fin 3` は `0` ・`1` ・`2` を表し、`Fin 0` は全く値を持ちません。`Fin n` はある `Nat` とそれが `n` より小さいことの証明を含む構造体であるため、`Fin` の定義は `Subtype` に似ています: + ```lean {{#example_decl Examples/ProgramsProofs/Fin.lean Fin}} ``` + + +Leanは `Fin` の値を数値として便利に使うために `ToString` と `OfNat` のインスタンスを有しています。つまり、`{{#example_in Examples/ProgramsProofs/Fin.lean fiveFinEight}}` の結果は `{val := 5, isLt := _}` ではなく `{{#example_out Examples/ProgramsProofs/Fin.lean fiveFinEight}}` です。 + +与えた数値がその範囲より大きい場合に `OfNat` インスタンスは失敗ではなく範囲の値によるその値の剰余の `Fin` を返します。つまり `{{#example_in Examples/ProgramsProofs/Fin.lean finOverflow}}` はコンパイルエラーにならずに `{{#example_out Examples/ProgramsProofs/Fin.lean finOverflow}}` となります。 + + + +戻り値の型において、見つかったインデックスとして返される `Fin` はそれが見つかったデータ構造との関連をより明確にします。[前節](./arrays-termination.md#proving-termination) での `Array.find` はその有効性に関する情報が失われているため、そのインデックスを使って配列検索がすぐには実行できません。より具体的な型によって、プログラムを著しく複雑にすることなく使用できる値が返されます: + ```lean {{#example_decl Examples/ProgramsProofs/Fin.lean ArrayFindHelper}} {{#example_decl Examples/ProgramsProofs/Fin.lean ArrayFind}} ``` + + +## 演習問題 + + +与えられた値の1つ大きい数値が範囲内であればその `Fin` を、そうでなければ `none` を返す関数 `Fin.next? : Fin n → Option (Fin n)` を書いてください。これが以下に対して + ```lean {{#example_in Examples/ProgramsProofs/Fin.lean nextThreeFin}} ``` + + +以下を出力し、 + ```output info {{#example_out Examples/ProgramsProofs/Fin.lean nextThreeFin}} ``` + + +また以下に対して + ```lean {{#example_in Examples/ProgramsProofs/Fin.lean nextSevenFin}} ``` + + +以下を出力することを確かめてください。 + ```output info {{#example_out Examples/ProgramsProofs/Fin.lean nextSevenFin}} ```