association lists

This module defines the well-known assoc and rassoc, which associates from right to left.

Require Export list_support.

Section Assoc.
  Variable A B : Type.
  Variable aeq : eq_type A.
  Variable beq : eq_type B.

Basic definitions and lemmas


  Fixpoint assoc(l : list (A × B))(a : A) : option B :=
    match l with
      | []None
      | ab :: lif aeq a (fst ab) then Some (snd ab) else assoc l a
    end.

  Fixpoint rassoc(l : list (A × B))(b : B) : option A :=
    match l with
      | []None
      | ab :: lif beq b (snd ab) then Some (fst ab) else rassoc l b
    end.

  Lemma assoc_cons_split :
    (P : option BProp)(a1 a2 : A)(b : B)(l : list (A × B)),
      (a1 = a2P (Some b)) →
      (a1 a2P (assoc l a2)) →
        P (assoc ((a1, b) :: l) a2).

  Lemma assoc_cons_first :
    (a : A)(b : B)(l : list (A × B)),
      assoc ((a, b) :: l) a = Some b.

  Lemma assoc_cons_tail :
    (a1 a2 : A)(b : B)(l : list (A × B)),
      a1 a2
        assoc ((a1, b) :: l) a2 = assoc l a2.

  Lemma rassoc_cons_split :
    (P : option AProp)(a : A)(b1 b2 : B)(l : list (A × B)),
      (b1 = b2P (Some a)) →
      (b1 b2P (rassoc l b2)) →
        P (rassoc ((a, b1) :: l) b2).

  Lemma rassoc_cons_first :
    (a : A)(b : B)(l : list (A × B)),
      rassoc ((a, b) :: l) b = Some a.

  Lemma rassoc_cons_tail :
    (a : A)(b1 b2 : B)(l : list (A × B)),
      b1 b2
        rassoc ((a, b1) :: l) b2 = rassoc l b2.

  Lemma rassoc_assoc_none :
    (l : list (A × B))(a : A)(b : B),
      rassoc l b = None
        assoc l a Some b.

  Lemma assoc_rassoc_some :
    (l : list (A × B))(a : A)(b : B),
      assoc l a = Some b
        is_some (rassoc l b).

  Lemma assoc_append_split :
    (P : option BProp)(l1 l2 : list (A × B))(a : A),
      (is_some (assoc l1 a) → P (assoc l1 a)) →
      (is_none (assoc l1 a) → P (assoc l2 a)) →
        P (assoc (l1 ++ l2) a).

  Lemma assoc_map_split :
    (C : Type)(f : CA × B)(l : list C)(a : A),
      (assoc (map f l) a = None (c : C), In c lfst (f c) a)
      
      (c : C), In c l
        fst (f c) = a assoc (map f l) a = Some (snd (f c)).

Injective association lists


  Definition injective_assoc(l : list (A × B)) : Prop :=
    (a1 a2 : A),
      assoc l a1 = assoc l a2
      is_some (assoc l a1) →
        a1 = a2.

  Lemma injective_assoc_empty : injective_assoc [].

  Lemma injective_assoc_cons_different :
    (l : list (A × B))(a : A)(b : B),
      injective_assoc l
      ((a : A), assoc l a Some b) →
        injective_assoc ((a, b) :: l).

  Lemma injective_assoc_cons_rassoc :
    (l : list (A × B))(a : A)(b : B),
      injective_assoc l
      rassoc l b = None
        injective_assoc ((a, b) :: l).

  Lemma injective_assoc_append :
    (l1 l2 : list (A × B)),
      injective_assoc l1
      injective_assoc l2
      ((a1 a2 : A),
             is_some (assoc l1 a1) →
               assoc l1 a1 assoc l2 a2) →
        injective_assoc (l1 ++ l2).

Functional association lists


  Inductive assoc_mapping : list (A × B) → Prop :=
    | assoc_mapping_nil : assoc_mapping []
    | assoc_mapping_cons :
        (a : A)(b : B)(l : list (A × B)),
          assoc_mapping l
            is_none (assoc l a) → assoc_mapping ((a, b) :: l).

  Lemma assoc_mapping_tail :
    (a : A)(b : B)(l : list (A × B)),
      assoc_mapping ((a, b) :: l) →
        assoc_mapping l.

  Lemma assoc_mapping_cons_first :
    (a : A)(b : B)(l : list (A × B)),
      assoc_mapping ((a, b) :: l) →
        is_none (assoc l a).

  Lemma rassoc_assoc_some :
    (l : list (A × B))(a : A)(b : B),
      assoc_mapping l
      rassoc l b = Some a
        assoc l a = Some b.

  Lemma injective_assoc_tail :
    (a : A)(b : B)(l : list (A × B)),
      assoc_mapping ((a, b) :: l) →
      injective_assoc ((a, b) :: l) →
        injective_assoc l.

  Lemma assoc_rassoc_inj_some :
    (l : list (A × B))(a : A)(b : B),
      assoc_mapping l
      injective_assoc l
      assoc l a = Some b
        rassoc l b = Some a.

Misc


  Lemma assoc_In : (l : list (A × B))(a : A)(b : B),
    assoc l a = Some bIn (a, b) l.

  Lemma assoc_In_rev : (l : list (A × B))(a : A)(b : B),
    assoc_mapping l
    In (a, b) l
      assoc l a = Some b.

  Lemma incl_assoc_some :
    (l1 l2 : list (A × B))(a : A),
      assoc_mapping l2
      incl l1 l2
      is_some (assoc l1 a) →
        is_some (assoc l2 a).

  Definition assoc_disjoint_keys(l1 l2 : list (A × B)) : Prop :=
    (a : A),
      (is_some (assoc l1 a) → is_none (assoc l2 a))
      (is_some (assoc l2 a) → is_none (assoc l1 a)).

  Lemma assoc_disjoint_keys_right_tail :
    (a : A)(b : B)(l1 l2 : list (A × B)),
      assoc_disjoint_keys l1 ((a, b) :: l2) →
        assoc_disjoint_keys l1 l2.

End Assoc.

Implicit Arguments assoc [A B].
Implicit Arguments rassoc [A B].
Implicit Arguments assoc_map_split [A B C].
Implicit Arguments injective_assoc [A B].
Implicit Arguments assoc_mapping [A B].
Implicit Arguments assoc_mapping_tail [A B].
Implicit Arguments assoc_mapping_cons_first [A B].
Implicit Arguments assoc_disjoint_keys [A B].
Implicit Arguments assoc_disjoint_keys_right_tail [A B].

Section Assoc_2.
  Variable A : Type.
  Variable aeq : eq_type A.

  Lemma assoc_swap_pairs :
    (B : Type)(l : list (B × A))(a : A),
      assoc aeq (swap_pairs l) a = rassoc aeq l a.

  Lemma assoc_map_pair :
    (B C : Type)(f : A × BC)
          (l : list (A × B))(a : A),
      assoc aeq (map (fun(ab : A × B) ⇒ (fst ab, f ab)) l) a =
        match assoc aeq l a with
          | Some bSome (f (a, b))
          | NoneNone
        end.

Apply assoc to a whole list


  Fixpoint apply_assoc_map(m : list (A × A))(l : list A) : list A :=
    match l with
      | [][]
      | a :: l
        (match assoc aeq m a with
           | Some a'a'
           | Nonea
         end
        ) :: (apply_assoc_map m l)
    end.

  Lemma In_apply_assoc_map_member :
    (m : list (A × A))(a1 a2 : A)(l : list A),
      In a1 l
      assoc aeq m a1 = Some a2
        In a2 (apply_assoc_map m l).

  Lemma In_apply_assoc_map_non_member :
    (m : list (A × A))(a : A)(l : list A),
      In a l
      assoc aeq m a = None
        In a (apply_assoc_map m l).

  Lemma In_apply_assoc_map_destruct :
    (m : list (A × A))(a : A)(l : list A),
      In a (apply_assoc_map m l) →
        ((a' : A), assoc aeq m a' = Some a In a' l)
        (assoc aeq m a = None In a l).

  Lemma apply_assoc_map_support :
    (m : list (A × A))(l : list A),
      incl (apply_assoc_map m l) (apply_assoc_map m (list_support aeq l)).

  Lemma apply_assoc_map_append :
    (m : list (A × A))(l1 l2 : list A),
      apply_assoc_map m (l1 ++ l2) =
        (apply_assoc_map m l1) ++ (apply_assoc_map m l2).

  Lemma apply_assoc_map_flatten :
    (m : list (A × A))(ll : list (list A)),
      apply_assoc_map m (flatten ll) =
        flatten (map (apply_assoc_map m) ll).

End Assoc_2.

Implicit Arguments assoc_map_pair [A B C].
Implicit Arguments apply_assoc_map [A].