theory Scratch imports "~~/src/HOL/Library/FSet" begin datatype val = VNat nat | VRel "(val \ val) fset" lemma sum_nat_le_single: fixes x :: nat assumes y: "y \ S" and x: "x \ f y" and finite: "finite S" shows "x \ sum f S" proof - have "sum f S = sum f (insert y S)" using y by (metis insert_absorb) with finite have "sum f S = f y + sum f (S - {y})" by (metis sum.insert_remove) with x show ?thesis by linarith qed context includes fset.lifting begin lift_definition fsum :: "('a \ 'b) \ 'a fset \ 'b::comm_monoid_add" is sum . lemma fsum_cong[fundef_cong]: "A = B \ (\x. x |\| B \ g x = h x) \ fsum g A = fsum h B" by transfer' (rule sum.cong) function (sequential) count :: "val \ nat" where "count (VNat n) = 1" | "count (VRel t) = fsum (\(v, u). count v + count u) t" by pat_completeness auto termination apply (relation "measure size") subgoal by simp subgoal apply simp apply transfer apply (rule le_imp_less_Suc) apply (rule sum_nat_le_single) by auto subgoal apply simp apply transfer apply (rule le_imp_less_Suc) apply (rule sum_nat_le_single) by auto done end primrec count' :: "val \ nat" where "count' (VNat n) = 1" | "count' (VRel t) = fsum (\(v, u). v + u) (map_prod count' count' |`| t)" end