ITree.Events.MapDefault

Mutable map whose lookup operation provides a default value.



Section Map.

  Variables (K V : Type).

  Variant mapE (d:V) : Type -> Type :=
  | Insert : K -> V -> mapE d unit
  | LookupDef : K -> mapE d V
  | Remove : K -> mapE d unit
  .

  Arguments Insert {d}.
  Arguments LookupDef {d}.
  Arguments Remove {d}.

  Definition insert {E d F} `{(mapE d) +? F -< E} : K -> V -> itree E unit := fun k v => trigger (Insert k v).
  Definition lookup_def {E d F} `{(mapE d) +? F -< E} : K -> itree E V := fun k => trigger (LookupDef k).
  Definition remove {E d F} `{(mapE d) +? F -< E} : K -> itree E unit := fun k => trigger (Remove k).

  Import Structures.Maps.

  Context {map : Type}.
  Context {M : Map K V map}.

  Definition lookup_default {K V} `{Map K V} k d m :=
    match Maps.lookup k m with
    | Some v' => v'
    | None => d
    end.

  Definition handle_map {E d} : mapE d ~> stateT map (itree E) :=
    fun _ e env =>
      match e with
      | Insert k v => Ret (Maps.add k v env, tt)
      | LookupDef k => Ret (env, lookup_default k d env)
      | Remove k => Ret (Maps.remove k env, tt)
      end.

  (* SAZ: I think that all of these run_foo functions should be renamed
     interp_foo.  That would be more consistent with the idea that 
     we define semantics by nested interpretation.  Also, it seems a bit
     strange to define interp_map in terms of interp_state.
  *)


  (* The appropriate notation of the equivalence on the state associated with
     the MapDefault effects.  Two maps are equivalent if they yield the same
     answers under lookup_default *)

  Definition eq_map (d:V) (m1 m2 : map) : Prop :=
    forall k, lookup_default k d m1 = lookup_default k d m2.

  Context {d : V}.

  #[global] Instance setoid_map : setoid map | 50.
    econstructor. Unshelve. 2 : exact (@eq_map d).
    constructor; repeat intro; eauto; etransitivity; eauto.
  Qed.

  #[global] Instance trigger_stateT_map {E} : Trigger E (stateT map (itree E)).
  Proof.
    eapply @Trigger_MonadT. typeclasses eauto.
    eapply MonadT_StateT. exact setoid_map.
  Qed.

  Definition interp_map {E d F} `{mapE d +? F -< E}
    : itree E ~> stateT map (itree F) :=
    interp (over handle_map).

End Map.

Arguments insert {K V E d _ _}.
Arguments lookup_def {K V E d _ _}.
Arguments remove {K V E d _ _}.
Arguments interp_map {K V map M _ _ _ _ H} [T].
Arguments eq_map {K V map M d}.