1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
|
From Coq Require Import List SetoidList.
Require Import
MathClasses.interfaces.abstract_algebra MathClasses.interfaces.monads MathClasses.theory.monads.
Import ListNotations.
(* The below belongs in the stdlib *)
Section equivlistA_misc.
Context `{Equivalence A eqA}.
Lemma NoDupA_singleton x : NoDupA eqA [x].
Proof. apply NoDupA_cons. intros E. inversion E. auto. Qed.
Global Instance equivlistA_cons_proper: Proper (eqA ==> equivlistA eqA ==> equivlistA eqA) cons.
Proof.
assert (∀ x₁ x₂ l₁ l₂ x, eqA x₁ x₂ → equivlistA eqA l₁ l₂ → InA eqA x (x₁ :: l₁) → InA eqA x (x₂ :: l₂)) as aux.
intros ? ? ? ? ? E1 E2 E3. inversion_clear E3.
apply InA_cons_hd. now rewrite <-E1.
apply InA_cons_tl. now rewrite <-E2.
split; eapply aux; auto; now symmetry.
Qed.
Lemma InA_singleton x y : InA eqA x [y] ↔ eqA x y.
Proof.
split; intros E.
inversion_clear E; auto. now destruct (proj1 (InA_nil eqA x)).
rewrite E. intuition.
Qed.
Lemma equivlistA_cons_nil x l : ¬equivlistA eqA (x :: l) [].
Proof. intros E. now eapply InA_nil, E, InA_cons_hd. Qed.
Lemma equivlistA_nil_eq l : equivlistA eqA l [] → l ≡ [].
Proof. induction l. easy. intros E. edestruct equivlistA_cons_nil; eauto. Qed.
Lemma InA_double_head z x l : InA eqA z (x :: x :: l) ↔ InA eqA z (x :: l).
Proof. split; intros E1; auto. inversion_clear E1; auto. Qed.
Lemma InA_permute_heads z x y l : InA eqA z (x :: y :: l) → InA eqA z (y :: x :: l).
Proof. intros E1. inversion_clear E1 as [|?? E2]; auto. inversion_clear E2; auto. Qed.
Lemma equivlistA_double_head x l : equivlistA eqA (x :: x :: l) (x :: l).
Proof. split; apply InA_double_head. Qed.
Lemma equivlistA_permute_heads x y l : equivlistA eqA (x :: y :: l) (y :: x :: l).
Proof. split; apply InA_permute_heads. Qed.
Lemma InA_app_ass z l₁ l₂ l₃ : InA eqA z (l₁ ++ (l₂ ++ l₃)) ↔ InA eqA z ((l₁ ++ l₂) ++ l₃).
Proof. now rewrite app_ass. Qed.
Lemma InA_app_nil_l z l : InA eqA z ([] ++ l) ↔ InA eqA z l.
Proof. firstorder. Qed.
Lemma InA_app_nil_r z l : InA eqA z (l ++ []) ↔ InA eqA z l.
Proof. now rewrite app_nil_r. Qed.
Lemma equivlistA_app_ass l₁ l₂ l₃ : equivlistA eqA (l₁ ++ (l₂ ++ l₃)) ((l₁ ++ l₂) ++ l₃).
Proof. now rewrite app_ass. Qed.
Lemma equivlistA_app_nil_l l : equivlistA eqA ([] ++ l) l.
Proof. reflexivity. Qed.
Lemma equivlistA_app_nil_r l : equivlistA eqA (l ++ []) l.
Proof. now rewrite app_nil_r. Qed.
Lemma InA_comm z l₁ l₂ : InA eqA z (l₁ ++ l₂) → InA eqA z (l₂ ++ l₁).
Proof. rewrite !(InA_app_iff _). tauto. Qed.
Lemma equivlistA_app_comm l₁ l₂ : equivlistA eqA (l₁ ++ l₂) (l₂ ++ l₁).
Proof. split; apply InA_comm. Qed.
Lemma InA_app_idem z l : InA eqA z (l ++ l) ↔ InA eqA z l.
Proof. rewrite (InA_app_iff _). tauto. Qed.
Lemma equivlistA_app_idem l : equivlistA eqA (l ++ l) l.
Proof. split; apply InA_app_idem. Qed.
Global Instance: Proper (equivlistA eqA ==> equivlistA eqA ==> equivlistA eqA) (@app A).
Proof. intros ?? E1 ?? E2 ?. rewrite !(InA_app_iff _), E1, E2. tauto. Qed.
Inductive PermutationA : list A → list A → Prop :=
| permA_nil: PermutationA [] []
| permA_skip x₁ x₂ l₁ l₂ : eqA x₁ x₂ → PermutationA l₁ l₂ → PermutationA (x₁ :: l₁) (x₂ :: l₂)
| permA_swap x y l : PermutationA (y :: x :: l) (x :: y :: l)
| permA_trans l₁ l₂ l₃ : PermutationA l₁ l₂ → PermutationA l₂ l₃ -> PermutationA l₁ l₃.
Hint Constructors PermutationA.
Global Instance: Equivalence PermutationA.
Proof.
split.
intros l. induction l; intuition.
intros l₁ l₂. induction 1; eauto. apply permA_skip; intuition.
intros ???. now apply permA_trans.
Qed.
Global Instance PermutationA_cons :
Proper (eqA ==> PermutationA ==> PermutationA) (@cons A).
Proof. repeat intro. now apply permA_skip. Qed.
Lemma PermutationA_app_head l₁ l₂ k :
PermutationA l₁ l₂ → PermutationA (k ++ l₁) (k ++ l₂).
Proof. intros. induction k. easy. apply permA_skip; intuition. Qed.
Global Instance PermutationA_app :
Proper (PermutationA ==> PermutationA ==> PermutationA) (@app A).
Proof.
intros l₁ l₂ Pl k₁ k₂ Pk.
induction Pl.
easy.
now apply permA_skip.
etransitivity.
rewrite <-!app_comm_cons. now apply permA_swap.
rewrite !app_comm_cons. now apply PermutationA_app_head.
do 2 (etransitivity; try eassumption).
apply PermutationA_app_head. now symmetry.
Qed.
Lemma PermutationA_app_tail l₁ l₂ k :
PermutationA l₁ l₂ → PermutationA (l₁ ++ k) (l₂ ++ k).
Proof. intros E. now rewrite E. Qed.
Lemma PermutationA_cons_append l x :
PermutationA (x :: l) (l ++ x :: nil).
Proof. induction l. easy. simpl. rewrite <-IHl. intuition. Qed.
Lemma PermutationA_app_comm l₁ l₂ :
PermutationA (l₁ ++ l₂) (l₂ ++ l₁).
Proof.
induction l₁.
now rewrite app_nil_r.
rewrite <-app_comm_cons, IHl₁.
now rewrite app_comm_cons, PermutationA_cons_append, <-app_assoc.
Qed.
Lemma PermutationA_cons_app l l₁ l₂ x :
PermutationA l (l₁ ++ l₂) → PermutationA (x :: l) (l₁ ++ x :: l₂).
Proof.
intros E. rewrite E.
now rewrite app_comm_cons, PermutationA_cons_append, <-app_assoc.
Qed.
Lemma PermutationA_middle l₁ l₂ x :
PermutationA (x :: l₁ ++ l₂) (l₁ ++ x :: l₂).
Proof. now apply PermutationA_cons_app. Qed.
Lemma PermutationA_equivlistA l₁ l₂ :
PermutationA l₁ l₂ → equivlistA eqA l₁ l₂.
Proof.
induction 1.
reflexivity.
now apply equivlistA_cons_proper.
now apply equivlistA_permute_heads.
etransitivity; eassumption.
Qed.
Lemma NoDupA_equivlistA_PermutationA l₁ l₂ :
NoDupA eqA l₁ → NoDupA eqA l₂ → equivlistA eqA l₁ l₂ → PermutationA l₁ l₂.
Proof.
intros Pl₁. revert l₂. induction Pl₁ as [|x l₁ E1].
intros. now rewrite equivlistA_nil_eq by now symmetry.
intros l₂ Pl₂ E2.
destruct (@InA_split _ eqA l₂ x) as [l₂h [y [l₂t [E3 ?]]]].
rewrite <-E2. intuition.
subst. transitivity (y :: l₁); [intuition |].
apply PermutationA_cons_app, IHPl₁.
now apply NoDupA_split with y.
apply equivlistA_NoDupA_split with x y; intuition.
Qed.
End equivlistA_misc.
Arguments PermutationA {A} _ _ _.
Notation "( x ::)" := (cons x) (only parsing) : mc_scope.
Notation "(:: l )" := (λ x, cons x l) (only parsing) : mc_scope.
Arguments app {A} _ _.
Section contents.
Context `{Setoid A}.
Global Instance list_equiv: Equiv (list A) := eqlistA (=).
Global Instance list_nil: MonUnit (list A) := [].
Global Instance list_app: SgOp (list A) := app.
Global Instance cons_proper: Proper (=) (@cons A).
Proof. repeat intro. now apply eqlistA_cons. Qed.
Instance: Setoid (list A).
Proof. constructor; apply _. Qed.
Instance app_proper: Proper ((=) ==> (=) ==> (=)) (@app A).
Proof. apply _. Qed.
Global Instance: Monoid (list A).
Proof.
repeat (split; try apply _).
intros x y z. unfold sg_op, list_app. now rewrite app_ass.
now repeat intro.
intros x. change (x ++ [] = x).
now rewrite app_nil_end.
Qed.
End contents.
Lemma list_equiv_eq {A} (x y : list A) :
@list_equiv A (≡) x y ↔ x ≡ y.
Proof. split. induction 1. reflexivity. now f_equal. intros. now subst. Qed.
#[global]
Instance list_join: MonadJoin list := λ _, fix list_join ll :=
match ll with
| [] => []
| l :: ll => l & list_join ll
end.
#[global]
Instance list_map: SFmap list := map.
#[global]
Instance list_ret: MonadReturn list := λ _ x, [x].
#[global]
Instance list_join_proper `{Setoid A} : Proper (=) (@list_join A).
Proof.
intros l. induction l; intros k E; inversion_clear E; try reflexivity.
simpl. apply app_proper; auto.
Qed.
#[global]
Instance list_ret_proper `{Equiv A}: Proper (=) (list_ret A).
Proof. compute. firstorder. Qed.
#[global]
Instance list_map_proper `{Setoid A} `{Setoid B} :
Proper (((=) ==> (=)) ==> ((=) ==> (=))) (list_map A B).
Proof.
intros f g E1 l. induction l; intros k E2; inversion_clear E2.
reflexivity.
simpl. apply cons_proper; auto.
Qed.
Lemma list_join_app `{Setoid A} (l k : list (list A)) :
join (l & k) = join l & join k.
Proof.
unfold join, list_join, sg_op, list_app.
induction l; simpl; try reflexivity.
now rewrite IHl, app_assoc.
Qed.
Lemma list_map_app `{Equiv A} `{Equiv B} `{!Setoid_Morphism (f : A → B)} (l k : list A) :
sfmap f (l & k) = sfmap f l & sfmap f k.
Proof. pose proof (setoidmor_b f). now setoid_rewrite map_app. Qed.
Local Instance: SFunctor list.
Proof.
split; try apply _; unfold sfmap, list_map, compose.
intros. intros ???. now rewrite map_id.
intros A ? B ? C ? f ? g ? ?? E.
pose proof (setoidmor_a f). pose proof (setoidmor_b f).
pose proof (setoidmor_a g). now rewrite <-E, map_map.
Qed.
#[global]
Instance: StrongMonad list.
Proof.
split; try apply _; unfold compose, id, sfmap, join, ret.
intros A ? B ? f [???].
intros ?? E. now rewrite <-E.
intros A ? B ? f ? l k E. pose proof (setoidmor_a f). pose proof (setoidmor_b f).
rewrite <-E. clear E. induction l; try reflexivity.
simpl. setoid_rewrite <-IHl. now apply list_map_app.
intros A ?? [|?] k E; inversion_clear E; try reflexivity.
simpl. rewrite right_identity. now apply cons_proper.
intros A ? ? l k E. rewrite <-E. clear E. induction l; try reflexivity.
simpl. now rewrite IHl.
intros A ?? l k E. rewrite <-E. clear E. induction l; try reflexivity.
simpl. now rewrite IHl, list_join_app.
Qed.
#[global]
Instance: FullMonad list.
Proof. apply strong_monad_default_full_monad. Qed.
(*
(* so far so good, but now: *)
Global Instance inj: InjectToSeq list := λ _ x, x :: nil.
(* universe inconsistency... *)
Global Instance sm: SeqToMonoid A (list A) := λ _ _ _ f, fold_right ((&) ∘ f) mon_unit.
Instance: Equiv A := eq.
Instance inj_mor: Setoid_Morphism inj.
Section sm_mor.
Context `{Monoid M} (f: A -> M).
Lemma sm_app (a a': list A):
sm M _ _ f (a ++ a') = sm M _ _ f a & sm M _ _ f a'.
Proof with reflexivity.
induction a; simpl; intros.
rewrite monoid_lunit...
unfold compose. rewrite IHa, associativity...
Qed.
Global Instance: Setoid_Morphism f → Monoid_Morphism (sm M _ _ f).
Proof.
intros.
repeat (constructor; try apply _). intros. apply sm_app.
reflexivity.
Qed.
End sm_mor.
Global Instance: @Sequence A (list A) eq _ _ _ _ _.
Proof with try reflexivity.
apply (Build_Sequence A (list A) eq _ _ _ _ _ _ _ inj_mor _).
unfold proves_free.
simpl.
split; repeat intro.
destruct i.
repeat (simpl in *; unfold compose).
rewrite H.
apply monoid_runit.
destruct b.
pose proof (H tt).
clear H. rename H0 into H.
simpl in *.
change (∀ x y1 : A, x = y1 → ua.variety_equiv varieties.monoid.theory y tt (proj1_sig y0 tt (inj x)) (setoidcat.f _ _ (f tt) y1)) in H.
revert a.
destruct y0.
simpl in *.
pose proof (varieties.monoid.from_object y).
assert (universal_algebra.Implementation varieties.monoid.sig
(λ _ : universal_algebra.sorts varieties.monoid.sig, list A)).
exact (ua.variety_op _ (varieties.monoid.object (list A))).
pose proof (@varieties.monoid.morphism_from_ua (list A) _ y _ (ua.variety_op _ (varieties.monoid.object (list A))) (ua.variety_op _ y) x h _ _ tt).
induction a.
change (x tt mon_unit = mon_unit).
apply preserves_mon_unit.
replace (a :: a0) with ((a :: nil) & a0)...
rewrite preserves_sg_op, IHa.
rewrite (H a a)...
Qed. (* todo: clean up *)
*)
|