Module aevalR_first_try.
Inductive aevalR : aexp -> nat -> Prop :=
| E_ANum  : forall (n: nat),
aevalR (ANum n) n
| E_APlus : forall (e1 e2: aexp) (n1 n2: nat),
aevalR e1 n1 ->
aevalR e2 n2 ->
aevalR (APlus e1 e2) (n1 + n2)
| E_AMinus: forall (e1 e2: aexp) (n1 n2: nat),
aevalR e1 n1 ->
aevalR e2 n2 ->
aevalR (AMinus e1 e2) (n1 - n2)
| E_AMult : forall (e1 e2: aexp) (n1 n2: nat),
aevalR e1 n1 ->
aevalR e2 n2 ->
aevalR (AMult e1 e2) (n1 * n2).
(** It will be convenient to have an infix notation for [aevalR].  We'll write [e \\ n] to mean that arithmetic expression [e] evaluates to value [n].  (This notation is one place where the limitation to ASCII symbols becomes a little bothersome.  The standard notation for the evaluation relation is a double down-arrow.  We'll typeset it like this in the HTML version of the notes and use a double slash as the closest approximation in [.v] files.)  *)
Notation "e '\\' n"
:= (aevalR e n)
(at level 50, left associativity)
: type_scope.
End aevalR_first_try.
(** In fact, Coq provides a way to use this notation in the definition of [aevalR] itself.  This reduces confusion by avoiding situations where we're working on a proof involving statements in the form [e \\ n] but we have to refer back to a definition written using the form [aevalR e n].  We do this by first "reserving" the notation, then giving the definition together with a declaration of what the notation means. *)
Reserved Notation "e '\\' n" (at level 50, left associativity).
Inductive aevalR : aexp -> nat -> Prop :=
| E_ANum : forall (n:nat),
(ANum n) \\ n
| E_APlus : forall (e1 e2: aexp) (n1 n2 : nat),
(e1 \\ n1) -> (e2 \\ n2) -> (APlus e1 e2) \\ (n1 + n2)
| E_AMinus : forall (e1 e2: aexp) (n1 n2 : nat),
(e1 \\ n1) -> (e2 \\ n2) -> (AMinus e1 e2) \\ (n1 - n2)
| E_AMult :  forall (e1 e2: aexp) (n1 n2 : nat),
(e1 \\ n1) -> (e2 \\ n2) -> (AMult e1 e2) \\ (n1 * n2)
where "e '\\' n" := (aevalR e n) : type_scope.
(* ================================================================= *)
(** ** Inference Rule Notation *)
(** In informal discussions, it is convenient to write the rules for [aevalR] and similar relations in the more readable graphical form of _inference rules_, where the premises above the line justify the conclusion below the line (we have already seen them in the [IndProp] chapter). *)
(** For example, the constructor [E_APlus]...  | E_APlus : forall (e1 e2: aexp) (n1 n2: nat), aevalR e1 n1 -> aevalR e2 n2 -> aevalR (APlus e1 e2) (n1 + n2)  ...would be written like this as an inference rule:  e1 \\ n1 e2 \\ n2 --------------------                         (E_APlus) APlus e1 e2 \\ n1+n2 *)
(** Formally, there is nothing deep about inference rules: they are just implications.  You can read the rule name on the right as the name of the constructor and read each of the linebreaks between the premises above the line (as well as the line itself) as [->].  All the variables mentioned in the rule ([e1], [n1], etc.) are implicitly bound by universal quantifiers at the beginning. (Such variables are often called _metavariables_ to distinguish them from the variables of the language we are defining.  At the moment, our arithmetic expressions don't include variables, but we'll soon be adding them.)  The whole collection of rules is understood as being wrapped in an [Inductive] declaration.  In informal prose, this is either elided or else indicated by saying something like "Let [aevalR] be the smallest relation closed under the following rules...". *)
(** For example, [\\] is the smallest relation closed under these rules:  -----------                               (E_ANum) ANum n \\ n  e1 \\ n1 e2 \\ n2 --------------------                         (E_APlus) APlus e1 e2 \\ n1+n2  e1 \\ n1 e2 \\ n2 ---------------------                        (E_AMinus) AMinus e1 e2 \\ n1-n2  e1 \\ n1 e2 \\ n2 --------------------                         (E_AMult) AMult e1 e2 \\ n1*n2 *)
(* ================================================================= *)
(** ** Equivalence of the Definitions *)
(** It is straightforward to prove that the relational and functional definitions of evaluation agree: *)

Theorem aeval_iff_aevalR : forall a n,
(a \\ n) <-> aeval a = n.