У меня есть версия, которая использует отношение Accessible
, чтобы показать, что сумма двух чисел, с которыми вы находите gcd, уменьшается при каждом рекурсивном вызове: https://gist.github.com/edwinb/1907723fbcfce2fde43a380b1faa3d2c#file-gcd-idr-L25
Это зависит от этогоот Prelude.Wellfounded
:
data Accessible : (rel : a -> a -> Type) -> (x : a) -> Type where
Access : (rec : (y : a) -> rel y x -> Accessible rel y) ->
Accessible rel x
Общая идея состоит в том, что вы можете сделать рекурсивный вызов, явно указав, что становится меньше, и предоставляя доказательство для каждого рекурсивного вызова, что он действительно становится меньше.Для gcd
это выглядит следующим образом (gcdt
для полной версии, поскольку gcd
входит в прелюдию):
gcdt : Nat -> Nat -> Nat
gcdt m n with (sizeAccessible (m + n))
gcdt m Z | acc = m
gcdt Z n | acc = n
gcdt (S m) (S n) | (Access rec)
= if m > n
then gcdt (minus m n) (S n) | rec _ (minusSmaller_1 _ _)
else gcdt (S m) (minus n m) | rec _ (minusSmaller_2 _ _)
sizeAccessible
определено в прелюдии и позволяет вам явно указатьздесь, что это сумма входов, которая становится меньше.Рекурсивный вызов меньше входного, потому что rec
является аргументом Access rec
.
Если вы хотите увидеть немного более подробно, что происходит, вы можете попробовать заменить minusSmaller_1
и minusSmaller_2
звонки с дырками, чтобы увидеть, что вы должны доказать:
gcdt : Nat -> Nat -> Nat
gcdt m n with (sizeAccessible (m + n))
gcdt m Z | acc = m
gcdt Z n | acc = n
gcdt (S m) (S n) | (Access rec)
= if m > n
then gcdt (minus m n) (S n) | rec _ ?smaller1
else gcdt (S m) (minus n m) | rec _ ?smaller2
Например:
*gcd> :t smaller1
m : Nat
n : Nat
rec : (y : Nat) ->
LTE (S y) (S (plus m (S n))) -> Accessible Smaller y
--------------------------------------
smaller1 : LTE (S (plus (minus m n) (S n))) (S (plus m (S n)))
Я нигде не знаю, что документы Accessible
в деталяхПо крайней мере для Idris (вы можете найти примеры для Coq), но есть больше примеров в библиотеках base
в Data.List.Views
, Data.Vect.Views
и Data.Nat.Views
.