Require Import ZArith. Inductive Exp : N -> Type := | Const : forall M, N -> Exp M | Add : forall M, Exp M -> Exp M -> Exp M | Mul : forall M, Exp M -> Exp M -> Exp M | Mod : forall M, Exp M -> Exp M. Arguments Const {M}. Arguments Add {M}. Arguments Mul {M}. Arguments Mod {M}. Infix "+" := Add. Infix "*" := Mul. Fixpoint eval {M}(e : Exp M) : N := match e with | Const x => x | Add e1 e2 => eval e1 + eval e2 | Mul e1 e2 => eval e1 * eval e2 | Mod ep => eval ep mod M end. Ltac reify e M := match e with | (?e1 + ?e2)%N => let e1p := reify constr:(e1) M in let e2p := reify constr:(e2) M in constr:(Add (M:=M) e1p e2p) | (?e1 * ?e2)%N => let e1p := reify constr:(e1) M in let e2p := reify constr:(e2) M in constr:(Mul (M:=M) e1p e2p) | (?ep mod ?M)%N => let epp := reify ep M in constr:(Mod (M:=M) epp) | _ => constr:(Const (M:=M) e) end.