forked from SSProve/ssprove
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMonadExamples.v
203 lines (165 loc) · 5.66 KB
/
MonadExamples.v
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
From Coq Require Import ssreflect List.
From Mon Require Export Base.
From Mon Require Import SPropBase SPropMonadicStructures Monoid.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Set Primitive Projections.
Set Universe Polymorphism.
(* The identity monad *)
Program Definition Identity : Monad :=
@mkMonad (fun X => X) (fun _ x => x) (fun X Y x f => f x) _ _ _.
(* The identity monad has a monad morphism to any other monad *)
Section IdentityInitial.
Context (M:Monad).
Program Definition ret_mmorph : MonadMorphism Identity M :=
@mkMorphism _ _ (@ret M) _ _.
Next Obligation. rewrite /bind monad_law1 //. Qed.
(* We just prove the existence, not the unicity... *)
End IdentityInitial.
Section State.
Context (S: Type).
Program Definition St : Monad :=
@mkMonad (fun X => S -> X × S) (fun A a s => ⟨a, s⟩)
(fun A B m f s => let ms := m s in f (nfst ms) (nsnd ms))
_ _ _.
Definition get : St S := fun s => ⟨s, s⟩.
Definition put (s:S) : St unit := fun s0 => ⟨tt, s⟩.
End State.
Section Update.
Context (M:monoid) (X:monoid_action M).
Definition UpdFromLaws pf1 pf2 pf3 : Monad :=
@mkMonad (fun A => X -> A × M) (fun A a x => ⟨a, e M⟩)
(fun A B m f x => let mx := m x in
let fx := f (nfst mx) (nsnd mx ⧕ x) in
⟨nfst fx, nsnd fx ⋅ nsnd mx⟩) pf1 pf2 pf3.
Import FunctionalExtensionality.
Program Definition Upd : Monad :=
UpdFromLaws _ _ _.
Next Obligation.
extensionality x ; rewrite monact_unit monoid_law2 //.
Qed.
Next Obligation.
extensionality x; rewrite monoid_law1 //.
Qed.
Next Obligation.
extensionality x. rewrite - !monact_mult !monoid_law3 //.
Qed.
End Update.
Section FreeMonad.
(* A signature where S is the type of operations and P describes the
arity of each operations *)
Context (S : Type) (P : S -> Type).
Inductive FreeF A : Type :=
| retFree : A -> FreeF A
| opr : forall s, (P s -> FreeF A) -> FreeF A.
Arguments opr [A] _ _.
Fixpoint bindFree A B (c : FreeF A) (f : A -> FreeF B) : FreeF B :=
match c with
| retFree a => f a
| opr s k => opr s (fun p => bindFree (k p) f)
end.
Import FunctionalExtensionality.
Program Definition Free : Monad :=
@mkMonad FreeF retFree bindFree _ _ _.
Next Obligation.
elim c => //= ? ? IH ; f_equal ; extensionality p ; apply IH.
Qed.
Next Obligation.
elim c => //= ? ? IH ; f_equal ; extensionality p ; apply IH.
Qed.
Definition op (s : S) : Free (P s) :=
opr s (@retFree _).
Definition trace := list { s : S & P s }.
Program Definition from_free (M:Monad) (f:forall s, M (P s))
: MonadMorphism Free M :=
@mkMorphism _ _
(fix from_free A (m:Free A) {struct m} :=
match m return M A with
| retFree a => ret a
| opr s k => bind (f s) (fun x => from_free A (k x))
end
) _ _.
Next Obligation.
induction m=> //=.
rewrite /bind monad_law1 //.
rewrite /bind monad_law3.
f_equal. extensionality a. apply H.
Qed.
End FreeMonad.
Section Partiality.
Inductive DivS := Omega.
Definition DivAr : DivS -> Type := fun 'Omega => False.
Definition Div := @Free DivS DivAr.
Definition Ω : Div False := op _ Omega.
End Partiality.
Section Exceptions.
Context (E:Type).
Inductive ExnS := Raise of E.
Definition ExnAr : ExnS -> Type := fun '(Raise _) => False.
Definition Exn := @Free ExnS ExnAr.
Definition raise : E -> Exn False := fun e => op _ (Raise e).
Definition catch {A} (m : Exn A) (merr : E -> Exn A) : Exn A :=
match m with
| retFree a => m
| @opr _ _ _ (Raise e) _ => merr e
end.
End Exceptions.
Section NonDeterminismSet.
Import SPropNotations FunctionalExtensionality SPropAxioms.
Program Definition NDSet : Monad :=
@mkMonad (fun X => X -> Prop)
(fun X x => fun x' => x = x')
(fun X Y c f => fun y => exists x, c x /\ f x y) _ _ _.
Next Obligation.
extensionality y; apply sprop_ext; do 2 split.
+ intros [x [eq H]]; induction eq=> //.
+ intro; exists a; intuition.
Qed.
Next Obligation.
extensionality y; apply sprop_ext; do 2 split.
+ intros [x [H eq]]. induction eq=> //.
+ intro. exists y. intuition.
Qed.
Next Obligation.
extensionality y; apply sprop_ext; do 2 split.
+ intros [b [[a [H1 H2]] H3]].
eexists ; split ; [|eexists;split]; eassumption.
+ intros [a [H1 [b [H2 H3]]]].
eexists ; split ; [eexists;split|]; eassumption.
Qed.
Definition pick_set : NDSet bool := fun b => True.
End NonDeterminismSet.
Section NonDeterminismList.
Lemma concat_map_nil : forall A (l : list A),
concat (List.map (fun x => x :: nil) l) = l.
Proof.
induction l.
- reflexivity.
- simpl. rewrite IHl. reflexivity.
Qed.
Program Definition ListM : Monad :=
@mkMonad (fun A => list A)
(fun A a => a :: nil)
(fun A B m f => concat (List.map f m)) _ _ _.
Next Obligation. apply app_nil_r. Qed.
Next Obligation. apply concat_map_nil. Qed.
Next Obligation.
induction c=> //=.
rewrite map_app concat_app IHc //.
Qed.
Definition choose {A} (l : list A) : ListM A := l.
Definition pick : ListM bool := true :: false :: nil.
End NonDeterminismList.
Section IO.
Context (Inp Oup : Type).
Inductive IOS : Type := Read : IOS | Write : Oup -> IOS.
Definition IOAr (op : IOS) : Type :=
match op with
| Read => Inp
| Write _ => unit
end.
Definition IO := @Free IOS IOAr.
Definition read : IO Inp := op _ Read.
Definition write (o:Oup) : IO unit := op _ (Write o).
End IO.