D1h: Rekursja ogonowa [TODO]


Require Import PeanoNat Nat.

From Typonomikon Require Import D5a.

Rekursja ogonowa (TODO)

Liczby Fibonacciego (TODO)


Module Fib.

Fixpoint fib (n : nat) : nat :=
match n with
| 0 => 0
| 1 => 1
| S (S n' as n'') => fib n'' + fib n'
end.

Fixpoint fib_tailrec_aux (n : nat) (a b : nat) : nat :=
match n with
| 0 => a
| S n' => fib_tailrec_aux n' b (a + b)
end.

Lemma fib_tailrec_aux_S :
  forall n a b : nat,
    fib_tailrec_aux (S n) a b = fib_tailrec_aux n b (a + b).

Compute fib_tailrec_aux 7 1 2.

Lemma fib_SS :
  forall n : nat,
    fib (S (S n)) = fib (S n) + fib n.

Definition fib_tailrec (n : nat) := fib_tailrec_aux n 0 1.

Lemma fib_tailrec_aux_spec :
  forall n k : nat,
    fib_tailrec_aux k (fib n) (fib (1 + n)) = fib (k + n).

Lemma fib_tailrec_spec :
  forall n : nat, fib_tailrec n = fib n.

End Fib.

Sklejanie list (TODO)


Fixpoint app_tailrec_aux {A : Type} (l acc : list A) : list A :=
match l with
| [] => acc
| h :: t => app_tailrec_aux t (h :: acc)
end.

Definition app' {A : Type} (l1 l2 : list A) : list A :=
  app_tailrec_aux (app_tailrec_aux l1 []) l2.

Lemma app_tailrec_aux_spec :
  forall (A : Type) (l1 l2 : list A),
    app_tailrec_aux l1 l2 = rev l1 ++ l2.

Lemma app'_spec :
  forall (A : Type) (l1 l2 : list A),
    app' l1 l2 = l1 ++ l2.

Definition rev' {A : Type} (l : list A) : list A :=
  app_tailrec_aux l [].

Lemma rev'_spec :
  forall {A : Type} (l : list A),
    rev' l = rev l.