End MODALITIES.
Global Instance klr_box_subrel_params: Params (@klr_box) 4.
Global Instance klr_diam_subrel_params: Params (@klr_diam) 4.
Hint Extern 0 (RIntro _ (klr_box _ _ _) _ _) =>
eapply klr_box_rintro : typeclass_instances.
Hint Extern 1 (RElim (klr_box _ _ _) _ _ _ _) =>
eapply klr_box_relim : typeclass_instances.
Hint Extern 0 (RExists _ (klr_diam _ _ _) _ _) =>
eapply klr_diam_rintro : typeclass_instances.
Hint Extern 1 (RElim (klr_diam _ _ _) _ _ _ _) =>
eapply klr_diam_relim : typeclass_instances.
Notation "[ l ] R" := (klr_box l R) (at level 65) : klr_scope.
Notation "< l > R" := (klr_diam l R) (at level 65) : klr_scope.
Notation "[] R" := (klr_box tt R) (at level 65) : klr_scope.
Notation "<> R" := (klr_diam tt R) (at level 65) : klr_scope.
(** For Kripke frames indexed by pairs, the following variants allow the components being related to access the labels used for transitions. *)
Section ARROW_MOD.
Context {W L1 L2} `{kf: KripkeFrame (L1 * L2) W}.
Definition klr_boxto {A B} (R : klr W A B) : klr W (L1 -> A) (L2 -> B) :=
fun w f g =>
forall l1 l2 w', acc (l1, l2) w w' -> R w' (f l1) (g l2).
Definition klr_diamat {A B} (R : klr W A B) : klr W (L1 * A) (L2 * B) :=
fun w '(l1, a) '(l2, b) =>
exists w', acc (l1, l2) w w' /\ R w' a b.
End ARROW_MOD.
Notation "[] -> R" := (klr_boxto R) (at level 65) : klr_scope.
Notation "<> * R" := (klr_diamat R) (at level 65) : klr_scope.
(** ** Flattening KLRs *)
(** When converting back to a standard [rel], we can quantify over all worlds. *)
Section UNKRIPKIFY.
Context `{kf: KripkeFrame}.
Definition rel_kvd {A B} (R: klr W A B): rel A B :=
fun x y => forall w, R w x y.
Global Instance rel_kvd_subrel A B:
Monotonic (@rel_kvd A B) ((- ==> subrel) ++> subrel).

(* Specifications: *)
Lemma rel_kvd_rintro {A B} (R: klr W A B) x y:
RIntro (forall w, R w x y) (rel_kvd R) x y.
Lemma rel_kvd_relim {A B} (R: klr W A B) w x y P Q:
RElim (R w) x y P Q ->
RElim (rel_kvd R) x y P Q.