Theory Mixed

theory Mixed
imports Stream_Examples GCD
header {* Mixed Recursion-Corecursion *}

(*<*)
theory Mixed
imports Stream_Examples GCD
begin
(*>*)

function primesrec :: "(nat * nat) => (stream + nat * nat) ΣΣ0 F ΣΣ0" where
  "primesrec (m, n) =
     (if (m = 0 ∧ n > 1) ∨ coprime m n then GUARD0 (n, CONT0 (m * n, Suc n))
     else (primesrec (m, Suc n)))"
by pat_completeness auto
termination
  apply (relation "measure (λ(m, n).
    if n = 0 then 1 else if coprime m n then 0 else m - n mod m)")
  apply (auto simp: mod_Suc intro: Suc_lessI)
      apply (metis One_nat_def coprime_Suc_nat gcd_nat.commute gcd_red_nat)
     apply (metis diff_less_mono2 lessI mod_less_divisor)
  done

definition primes :: "nat => nat => stream" where
  "primes = curry (corecUU0 primesrec)"

lemma primes_code:
  "primes m n =
    (if (m = 0 ∧ n > 1) ∨ coprime m n then SCons n (primes (m * n) (Suc n))
     else primes m (Suc n))"
  unfolding primes_def curry_def
  by (subst corecUU0, subst primesrec.simps)
    (simp del: primesrec.simps add: map_pre_J_def BNF_Comp.id_bnf_comp_def eval0_leaf0' corecUU0)

lemma primes: "primes 1 2 = SCons 2 (primes 2 3)"
  by (subst primes_code) auto

fun catalanrec :: "nat => (stream + nat) ΣΣ1 F ΣΣ1" where
  "catalanrec n =
     (if n > 0 then PLS1 (catalanrec (n - 1), GUARD1 (0, CONT1 (n+1))) else GUARD1 (1, CONT1 1))"

definition catalan :: "nat => stream" where
  "catalan = corecUU1 catalanrec"

lemma catalan_code:
  "catalan n =
    (if n > 0 then pls (catalan (n - 1)) (SCons 0 (catalan (n + 1)))
     else SCons 1 (catalan 1))"
  unfolding catalan_def
  by (subst corecUU1, subst catalanrec.simps)
    (simp del: catalanrec.simps add: map_pre_J_def BNF_Comp.id_bnf_comp_def
      eval1_\<oo>\<pp>1 eval1_leaf1' algΛ1_Inr o_eq_dest[OF Abs_Σ1_natural] corecUU1 pls_uniform)

(*<*)
end
(*>*)