File: FunctorFromMonad.v

package info (click to toggle)
coq-ext-lib 0.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 808 kB
  • sloc: makefile: 44; python: 31; sh: 4; lisp: 3
file content (118 lines) | stat: -rw-r--r-- 5,140 bytes parent folder | download | duplicates (2)
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
Require Import Relations.
Require Import ExtLib.Data.Fun.
Require Import ExtLib.Structures.Proper.
Require Import ExtLib.Structures.Monad.
Require Import ExtLib.Structures.FunctorRelations.
Require Import ExtLib.Structures.MonadLaws.

Set Implicit Arguments.
Set Strict Implicit.

Section stuff.

  Variable m : Type -> Type.
  Variable Monad_m : Monad m.
  Variable mleq : forall T, (T -> T -> Prop) -> m T -> m T -> Prop.
  Variable mproper : forall T (rT : relation T), Proper rT -> Proper (mleq rT).
  Variable FunctorOrder_mleq : FunctorOrder m mleq mproper.
  Variable MonadLaws_mleq : MonadLaws Monad_m mleq mproper.

  Definition compose (A B C : Type) (f : A -> B) (g : B -> C) : A -> C :=
    fun x => g (f x).

  Definition pure (T : Type) : T -> m T := @ret _ _ _.
  Definition fapply (T U : Type) (f : m (T -> U)) (x : m T) : m U :=
    bind f (fun f => bind x (fun x => ret (f x))).

  Existing Instance fun_trans.
  Existing Instance fun_refl.

  Variables A B C : Type.
  Context (rA : relation A) (rB : relation B) (rC : relation C)
          (pA : Proper rA) (pB : Proper rB) (pC : Proper rC).
  Context (Ra : PReflexive rA) (Rb : PReflexive rB) (Rc : PReflexive rC).
  Context (Ta : PTransitive rA) (Tb : PTransitive rB) (Tc : PTransitive rC).

  Instance fun_app_proper (A B : Type) (rA : relation A) (rB : relation B) (pA : Proper rA) (pB : Proper rB) (f : A -> B) x :
    proper f -> proper x ->
    proper (f x).
  Proof.
    intros. apply H. auto.
  Qed.

  Instance fun_abs (A B : Type) (rA : relation A) (rB : relation B) (pA : Proper rA) (pB : Proper rB) (f : A -> B) :
    (forall x, proper x -> proper (f x)) ->
    (forall x y, proper x -> proper y -> rA x y -> rB (f x) (f y)) ->
    proper (fun x => f x).
  Proof.
    intros. split; auto; eapply H.
  Qed.

  Ltac prove_proper x k :=
    match x with
      | _ => match goal with
               | [ H : proper x |- _ ] => k H
             end
      | bind ?A ?B => 
        prove_proper A ltac:(fun a => prove_proper B ltac:(fun b =>
          let H := fresh in
            assert (H : proper x); [ eapply bind_proper; eauto with typeclass_instances | k H ]))
      | ret ?A => 
        prove_proper A ltac:(fun a => 
          let H := fresh in
            assert (H : proper x); [ eapply ret_proper; eauto with typeclass_instances | k H ])
      | (fun x => _) =>
        let H := fresh in 
        assert (H : proper x); [ eapply fun_abs; intros; [ propers | repeat red; intros; prove_mleq ] | k H ]
      | _ => 
        let H := fresh in
          assert (H : proper x); [ eauto with typeclass_instances | k H ]
    end
  with prove_mleq :=
    try match goal with
          | |- proper (fun x => _) =>
            eapply fun_abs; intros; [ propers | repeat red; intros; prove_mleq ]
          | [ R : _ , H' : pfun_ext ?R _ ?F ?G |- ?R (?F _) (?G _) ] =>
            eapply H'; [ propers | propers | prove_mleq ]
          | [ H' : proper ?F |- ?R (?F _) (?F _) ] =>
            eapply H'; [ propers | propers | try assumption; prove_mleq ]
          | [ |- mleq _ (bind _ _) (bind _ _) ] =>
            eapply bind_respectful_leq; [ eauto with typeclass_instances | eauto with typeclass_instances | prove_mleq | intros; prove_mleq ]
          | [ |- mleq _ (ret _) (ret _) ] =>
            eapply ret_respectful_leq; [ eauto with typeclass_instances | eauto with typeclass_instances | prove_mleq ]
          | [ H : proper ?f |- pfun_ext _ _ ?f ?f ] => apply H
          | [ H : proper ?f |- pfun_ext _ _ (fun x => _) (fun y => _) ] => red; intros; prove_mleq
          | _ => eassumption
        end
  with propers :=
    match goal with 
      | |- proper ?X => prove_proper X ltac:(fun x => eapply x)
      | |- mleq _ ?X ?Y =>
        prove_proper X ltac:(fun x => prove_proper Y ltac:(fun x => idtac))
    end.

  Instance PReflexive_stuff : PReflexive 
     (pfun_ext (pfun_ext (pfun_ext rC pA) (Proper_pfun pB pC))
        (Proper_pfun pA pB)).
  Proof. intuition. Qed.

  Theorem bind_law : forall (f : A -> B) (g : B -> C),
    proper f -> proper g ->
    mleq (pfun_ext rC pA)
         (fapply (fapply (pure (@compose A B C)) (pure f)) (pure g))
         (pure (compose f g)).
  Proof.
    unfold fapply, pure, compose; simpl; intros.
    propers. 
    (eapply ptransitive; [ | | | | eapply (@bind_associativity _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    (eapply ptransitive; [ | | | | eapply (@bind_of_return _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    (eapply ptransitive; [ | | | | eapply (@bind_associativity _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    (eapply ptransitive; [ | | | | eapply (@bind_of_return _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    (eapply ptransitive; [ | | | | eapply (@bind_of_return _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    (eapply ptransitive; [ | | | | eapply (@bind_of_return _ _ _ _ MonadLaws_mleq) | ]); eauto with typeclass_instances; propers.
    eapply preflexive; eauto with typeclass_instances.
  Qed.

End stuff.

Print Assumptions bind_law.