forked from coq-community/math-classes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
option.v
136 lines (112 loc) · 3.95 KB
/
option.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
Require Import
MathClasses.interfaces.abstract_algebra MathClasses.interfaces.monads MathClasses.theory.jections MathClasses.theory.monads.
Inductive option_equiv A `{Equiv A} : Equiv (option A) :=
| option_equiv_Some : Proper ((=) ==> (=)) Some
| option_equiv_None : None = None.
Existing Instance option_equiv.
Hint Constructors option_equiv.
Section contents.
Context `{Setoid A}.
Lemma Some_ne_None x : Some x ≠ None.
Proof. intros E. inversion E. Qed.
Lemma None_ne_Some x : None ≠ Some x.
Proof. intros E. inversion E. Qed.
Global Instance: Setoid (option A).
Proof.
split.
intros [x|]. now apply option_equiv_Some. now apply option_equiv_None.
red. induction 1. now apply option_equiv_Some. now apply option_equiv_None.
intros x y z E. revert z. induction E.
intros z E2. inversion_clear E2.
apply option_equiv_Some. etransitivity; eassumption.
easy.
Qed.
Global Instance: Setoid_Morphism Some.
Proof. split; try apply _. now apply option_equiv_Some. Qed.
Global Instance: Injective Some.
Proof. split; try apply _. intros ? ? E. now inversion E. Qed.
Global Instance option_zero: MonUnit (option A) := None.
Global Instance option_op: SgOp (option A) := λ mx my,
match mx with
| Some x => Some x
| None => my
end.
Instance: Proper ((=) ==> (=) ==> (=)) option_op.
Proof. intros [?|] [?|] ? ???; simpl; try setoid_discriminate; auto. Qed.
Global Instance: Monoid (option A).
Proof. repeat (split; try apply _); now repeat intros [?|]. Qed.
Lemma option_equiv_alt x y :
x = y ↔ (∀ n, x = Some n ↔ y = Some n).
Proof.
split; intros E1.
intro. now rewrite E1.
destruct x, y.
now apply E1.
symmetry. now apply E1.
now apply E1.
easy.
Qed.
Global Program Instance option_dec `(A_dec : ∀ x y : A, Decision (x = y))
: ∀ x y : option A, Decision (x = y) := λ x y,
match x with
| Some r =>
match y with
| Some s => match A_dec r s with left _ => left _ | right _ => right _ end
| None => right _
end
| None =>
match y with
| Some s => right _
| None => left _
end
end.
Next Obligation. now apply (injective_ne Some). Qed.
Next Obligation. setoid_discriminate. Qed.
Next Obligation. setoid_discriminate. Qed.
End contents.
Hint Extern 10 (Equiv (option _)) => apply @option_equiv : typeclass_instances.
Lemma option_equiv_eq {A} (x y : option A) :
@option_equiv A (≡) x y ↔ x ≡ y.
Proof.
split.
induction 1. now f_equal. reflexivity.
intros. subst.
now assert (@Setoid A (@eq A)) by (split; apply _).
Qed.
Instance option_ret: MonadReturn option := λ A x, Some x.
Instance option_bind: MonadBind option := λ A B f x,
match x with
| Some a => f a
| None => None
end.
Instance option_ret_proper `{Equiv A} : Proper ((=) ==> (=)) (option_ret A).
Proof. intros x y E. now apply option_equiv_Some. Qed.
Instance option_bind_proper `{Setoid A} `{Setoid (option B)}: Proper (=) (option_bind A B).
Proof.
intros f₁ f₂ E1 x₁ x₂ [?|].
unfold option_bind. simpl. now apply E1.
easy.
Qed.
Instance: Monad option.
Proof.
repeat (split; try apply _); unfold bind, ret, option_bind, option_ret, compose.
intros. now apply setoids.ext_equiv_refl.
now intros ? ? ? [?|].
intros A ? B ? C ? ? f [???] g [???] [x|] [y|] E; try solve [inversion_clear E].
setoid_inject. cut (g x = g y); [|now rewrite E].
case (g x), (g y); intros E2; inversion_clear E2. now f_equiv. easy.
easy.
Qed.
Instance option_map: SFmap option := option_map.
Instance: FullMonad option.
Proof. apply @monad_default_full_monad. apply _. Qed.
Section map.
Context `{Setoid A} `{Setoid B} `{!Injective (f : A → B)}.
Global Instance: Injective (sfmap f).
Proof.
pose proof (injective_mor f).
repeat (split; try apply _).
intros [x|] [y|] E; try solve [inversion E | easy].
apply sm_proper. apply (injective f). now apply (injective Some).
Qed.
End map.