Skip to content

Commit 9c84acd

Browse files
committed
whileループを使うと証明ができなくなることを紹介する
resolve #2237
1 parent 7ca78ba commit 9c84acd

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

LeanByExample/DoSyntax/README.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/- # do 構文 -/

LeanByExample/DoSyntax/While.lean

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/- # while
2+
3+
`while` は、「ある条件が成り立っている間、同じ処理を繰り返す」ための構文です。`while P do B` という構文で用いて、条件 `P` が成り立つ間、命令 `B` を繰り返し実行します。
4+
-/
5+
6+
/-- 1から5までの数字をリストに詰めて返す -/
7+
def packOneToFive : List Nat := Id.run do
8+
let mut result := []
9+
let mut n := 1
10+
while n ≤ 5 do
11+
result := result ++ [n]
12+
n := n + 1
13+
return result
14+
15+
#guard packOneToFive = [1, 2, 3, 4, 5]
16+
17+
/- ## while ループと停止性
18+
19+
`while` ループを使うと、停止するとは限らない計算が(停止性の証明を与えてもいないのに)書けてしまいます。たとえば以下は、述語 `P : Nat → Bool` を成り立たせる最小の自然数を探してくる関数の例です。
20+
-/
21+
22+
/-- 述語 `P : Nat → Bool` を成り立たせる最小の自然数を返す -/
23+
def searchMinExample (P : Nat → Bool) : Nat := Id.run do
24+
let mut n := 0
25+
while !P n do
26+
n := n + 1
27+
return n
28+
29+
#guard searchMinExample (fun n => n % 7 = 1) = 1
30+
31+
/-
32+
なぜ停止性の証明が必要ないのかというと、`while` ループが内部で `Lean.Loop.forIn` という関数に展開されるのですが、これが [`partial`](#{root}/Modifier/Partial.md) で修飾された関数だからです。
33+
34+
したがって特に、`while` で定義された関数について何かを証明することはできません。たとえ明らかに停止する関数であっても、`while` で書かれた部分については証明不能になります。
35+
-/
36+
37+
/-- 明らかに停止するし明らかに`0`しか返さないはずの関数 -/
38+
def trivialWhile : Nat := Id.run do
39+
let mut m := 0
40+
while false do
41+
m := m + 1
42+
return m
43+
44+
-- 明らかなはずなのに全然証明できない
45+
set_option warn.sorry false in --#
46+
example : trivialWhile = 0 := by
47+
fail_if_success rfl
48+
fail_if_success try?
49+
sorry
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import LeanByExample.Diagnostic.GuardMsgs.ContainMsg
2+
3+
def searchMinExample (P : Nat → Bool) : Nat := Id.run do
4+
let mut n := 0
5+
while !P n do
6+
n := n + 1
7+
return n
8+
9+
/-- Lean.Loop.forIn -/
10+
#contain_msg in
11+
#reduce searchMinExample
12+
13+
/-- info: fun {β} {m} [Monad m] x init f => Lean.Loop.forIn.loop✝ f init -/
14+
#guard_msgs in --#
15+
#reduce @Lean.Loop.forIn

booksrc/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@
169169
- [Type: 型の型](./Type/Type.md)
170170
- [Vector: 長さ固定の配列](./Type/Vector.md)
171171

172+
- [do 構文](./DoSyntax/README.md)
173+
- [while: 停止するとは限らない繰り返し](./DoSyntax/While.md)
174+
172175
- [タクティク](./Tactic/README.md)
173176
- [<;>: 生成された全ゴールに適用](./Tactic/SeqFocus.md)
174177
- [ac_rfl: 可換性と結合性を使う](./Tactic/AcRfl.md)

0 commit comments

Comments
 (0)