(* Encoding is done by iteratively applying find_code *)
Fixpoint encode (c : code) (m : list A) {struct m} : list bool :=
  match m with
  | nil => nil
  | a :: b => find_code a c ++ encode c b
  end.

(* Specifications: *)
Theorem encode_app : forall l1 l2 c, encode c (l1 ++ l2) = encode c l1 ++ encode c l2.
Theorem encode_cons_inv : forall a l1 l m1, ~ In a m1 -> encode ((a, l1) :: l) m1 = encode l m1.
Theorem encode_permutation : forall (m : list A) (c1 c2 : code), permutation c1 c2 -> unique_prefix c1 -> encode c1 m = encode c2 m.
Theorem encode_permutation_val : forall m1 m2 c, permutation m1 m2 -> permutation (encode c m1) (encode c m2).