Section monoid_term_map.
(** Represents an arbitrary monoid. *)
Variable m : Monoid.
(** Represents the set of monoid elements. *)
Let E := E m.
(** Represents monoid values.  Note: In the development that follows, we will use binary trees and lists to represent monoid expressions. We will effectively flatten a tree and filter a list to "simplify" a given expression.  The code that flattens the tree representation does not need to care whether or not the leaves in the tree represent 0 (the monoid identity element), inverses, etc. Accordingly, distinguishing these elements in the definition of BTree would unnecessarily complicate the tree algorithms by adding more recursion cases.  Instead of doing this, we use two types to represent monoid expressions - trees to represent "terms" (expressions that are summed together) and Term. Term tracks whether or not a monoid value equals 0 (and later we will use a similar structure to indicate whether or not a given group element is an inverse). This makes this information available when needed (specifically when we eliminate 0s using list filtering) without complicating the tree algorithms. *)
Inductive Term : Set
:= term_0 : Term
|  term_const : E -> Term.
(** Accepts a term and returns the monoid value that it represents. *)
Definition Term_eval
:  Term -> E
:= Term_rec
(fun _ => E)
0
(fun x => x).
(** Accepts a term and returns true iff the term is zero. *)
Definition Term_is_zero
:  Term -> bool
:= Term_rec
(fun _ => bool)
true
(fun _ => false).

(** Proves that Term_is_zero is correct. *)
Theorem Term_is_zero_thm
:  forall t, Term_is_zero t = true -> Term_eval t = 0.