Definition Succ_e : Cobham :=
Comp 1 (Succ true) [Proj 1 0].
Opaque Succ_e.
Fixpoint Nat_e (n:nat) : Cobham :=
match n with
| 0 => Zero
| S n' => Comp 0 Succ_e [Nat_e n']
end.
Notation Plus_e := App_e.
Notation arity_Plus := arity_App.
Notation rec_bounded_Plus := rec_bounded_App.
Opaque Plus_e.
Fixpoint Plusl_e (ar:nat)(el:list Cobham) : Cobham :=
match el with
| nil => Zero_e ar
| e' :: el' => Comp ar Plus_e [e'; Plusl_e ar el']
end.
Opaque Plusl_e.
Definition Mult_e : Cobham :=
Rec2
(Zero_e 1)
(Comp 3 Plus_e [Proj 3 1; Proj 3 2])
(Comp 2 Smash [
One_e 2;
Comp 2 Smash [Comp 2 (Succ true) [Proj 2 0]; Comp 2 (Succ true) [Proj 2 1] ] ] ).
Opaque Mult_e.
Fixpoint Multl_e (ar:nat)(el:list Cobham) : Cobham :=
match el with
| nil => One_e ar
| e' :: el' => Comp ar Mult_e [e'; Multl_e ar el']
end.
Fixpoint Power_e (n:nat) : Cobham :=
match n with
| 0 => One_e 1
| S n' => Comp 1 Mult_e [Proj 1 0; Power_e n']
end.
Definition Poly_pow (ar:nat) (xn:pow) : Cobham :=
Comp ar (Power_e (snd xn)) [Proj ar (fst xn)].
Opaque Poly_pow.
Definition Poly_mon (ar:nat)(m:mon) : Cobham :=
Comp ar Mult_e [Comp ar (Nat_e (fst m)) nil; Multl_e ar (map (Poly_pow ar) (snd m))].
Opaque Poly_mon.
Definition Poly (p : pol) : Cobham :=
Plusl_e (fst p) (map (Poly_mon (fst p)) (snd p)).

Lemma Poly_correct : forall p l,
length (Sem (Poly p) l) = peval p (map (@length _) l).