Lvc.Constr.MapLookupList

Require Export Setoid Coq.Classes.Morphisms.
Require Import EqDec Computable Util LengthEq AutoIndTac.
Require Export CSet Containers.SetDecide.
Require Export MapBasics MapLookup MapUpdate.

Set Implicit Arguments.

Section MapLookupList.
  Variable X : Type.
  Context `{OrderedType X}.
  Variable Y : Type.

  Open Scope fmap_scope.

  Fixpoint lookup_list (m:XY) (L:list X) : list Y :=
    match L with
      | nilnil
      | x::Lm x::lookup_list m L
    end.

  Lemma update_with_list_app (A : list X) (B : list Y) E
    : length A = length B
    → update_with_list (A++) (B++) E = update_with_list A B (update_with_list E).

  Lemma lookup_list_length (m:XY) (L:list X)
    : length (lookup_list m L) = length L.

  Lemma lookup_list_agree (m :XY) (L:list X)
    : agree_on eq (of_list L) m
    → lookup_list m L = lookup_list L.

  Lemma of_list_lookup_list `{OrderedType Y} (m:XY) L
    : Proper (_eq ==> _eq) m
      → of_list (lookup_list m L) [=] lookup_set m (of_list L).

End MapLookupList.

Lemma lookup_id X (l:list X)
: lookup_list (@id X) l = l.

Global Instance update_with_list_inst X `{OrderedType X} Y `{OrderedType Y} :
  Proper (eq ==> eq ==> (@feq X Y _eq ) ==> (@feq _ _ _eq)) (@update_with_list X _ Y).

Global Instance lookup_list_inst X `{OrderedType X} Y:
  Proper ((@feq X Y eq) ==> eq ==> eq) (@lookup_list X Y).

Lemma update_with_list_lookup_list X `{OrderedType X} Y `{OrderedType Y} (E:XY)
     `{Proper _ (_eq ==> _eq) E} (Z : list X)
: @feq _ _ _eq (update_with_list Z (lookup_list E Z) E) E.

Lemma lookup_list_app X Y (A :list X) (E:XY)
: lookup_list E (A ++ ) = List.app (lookup_list E A) (lookup_list E ).

Lemma lookup_list_unique X `{OrderedType X} Y (Z:list X) (:list Y) f
: length Z = length
  → unique Z
  → lookup_list (f [Z <-- ]) Z = .

Hint Resolve lookup_list_agree : cset.