partial
partial
は部分関数(partial function)を定義するための構文です.
Lean では再帰関数も再帰的でない関数と同様に定義できますが,扱いは異なります.再帰的な関数 f
を定義すると,Lean は f
がすべての入力に対して必ず有限回の再帰で停止することを証明しようとします.自動的な証明が失敗すると,エラーになってしまいます.エラーを消すには,
- 停止することを手動で証明するか
- 停止性は保証しないと明示的にマークするか
どちらかの対応が必要です.関数の定義に partial
とマークすると, 停止性は保証しないとマークしたことになります.
/--
error: fail to show termination for
WithoutPartial.alternate
with errors
argument #2 was not used for structural recursion
failed to eliminate recursive application
alternate ys xs
argument #3 was not used for structural recursion
failed to eliminate recursive application
alternate ys xs
structural recursion cannot be used
Could not find a decreasing measure.
The arguments relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
xs ys
1) 38:24-39 ? ?
Please use `termination_by` to specify a decreasing measure.
-/
#guard_msgs (whitespace := lax) in
def alternate {α : Type} (xs ys : List α) : List α :=
match xs, ys with
| [], ys => ys
| x :: xs, ys => x :: alternate ys xs
-- `partial` を使うと,停止性の証明が不要になる
partial def alternate {α : Type} (xs ys : List α) : List α :=
match xs, ys with
| [], ys => ys
| x :: xs, ys => x :: alternate ys xs
#guard alternate [1, 3, 5] [2, 4, 6] = [1, 2, 3, 4, 5, 6]
なお,partial
とマークされた定義を元に新たに関数を定義するとき,再度 partial
とマークする必要はありません.
def more_alternate := @alternate