forked from agda/agda-stdlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCore.agda
203 lines (151 loc) · 6.58 KB
/
Core.agda
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
------------------------------------------------------------------------
-- The Agda standard library
--
-- Operations on and properties of decidable relations
--
-- This file contains some core definitions which are re-exported by
-- Relation.Nullary.Decidable
------------------------------------------------------------------------
{-# OPTIONS --cubical-compatible --safe #-}
module Relation.Nullary.Decidable.Core where
open import Agda.Builtin.Equality using (_≡_)
open import Level using (Level; Lift)
open import Data.Bool.Base using (Bool; T; false; true; not; _∧_; _∨_)
open import Data.Unit.Polymorphic.Base using (⊤)
open import Data.Product.Base using (_×_)
open import Data.Sum.Base using (_⊎_)
open import Function.Base using (_∘_; const; _$_; flip)
open import Relation.Nullary.Recomputable as Recomputable hiding (recompute-constant)
open import Relation.Nullary.Reflects as Reflects hiding (recompute; recompute-constant)
open import Relation.Nullary.Negation.Core
using (¬_; Stable; negated-stable; contradiction; DoubleNegation)
private
variable
a b : Level
A B : Set a
------------------------------------------------------------------------
-- Definition.
-- Decidability proofs have two parts: the `does` term which contains
-- the boolean result and the `proof` term which contains a proof that
-- reflects the boolean result. This definition allows the boolean
-- part of the decision procedure to compute independently from the
-- proof. This leads to better computational behaviour when we only care
-- about the result and not the proof. See README.Design.Decidability
-- for further details.
infix 2 _because_
record Dec (A : Set a) : Set a where
constructor _because_
field
does : Bool
proof : Reflects A does
open Dec public
pattern yes a = true because ofʸ a
pattern no ¬a = false because ofⁿ ¬a
------------------------------------------------------------------------
-- Flattening
module _ {A : Set a} where
From-yes : Dec A → Set a
From-yes (true because _) = A
From-yes (false because _) = ⊤
From-no : Dec A → Set a
From-no (false because _) = ¬ A
From-no (true because _) = ⊤
------------------------------------------------------------------------
-- Recompute
-- Given an irrelevant proof of a decidable type, a proof can
-- be recomputed and subsequently used in relevant contexts.
recompute : Dec A → Recomputable A
recompute = Reflects.recompute ∘ proof
recompute-constant : (a? : Dec A) (p q : A) → recompute a? p ≡ recompute a? q
recompute-constant = Recomputable.recompute-constant ∘ recompute
------------------------------------------------------------------------
-- Interaction with negation, sum, product etc.
infixr 1 _⊎-dec_
infixr 2 _×-dec_ _→-dec_
T? : ∀ x → Dec (T x)
T? x = x because T-reflects x
¬? : Dec A → Dec (¬ A)
does (¬? a?) = not (does a?)
proof (¬? a?) = ¬-reflects (proof a?)
_×-dec_ : Dec A → Dec B → Dec (A × B)
does (a? ×-dec b?) = does a? ∧ does b?
proof (a? ×-dec b?) = proof a? ×-reflects proof b?
_⊎-dec_ : Dec A → Dec B → Dec (A ⊎ B)
does (a? ⊎-dec b?) = does a? ∨ does b?
proof (a? ⊎-dec b?) = proof a? ⊎-reflects proof b?
_→-dec_ : Dec A → Dec B → Dec (A → B)
does (a? →-dec b?) = not (does a?) ∨ does b?
proof (a? →-dec b?) = proof a? →-reflects proof b?
------------------------------------------------------------------------
-- Relationship with booleans
-- `isYes` is a stricter version of `does`. The lack of computation
-- means that we can recover the proposition `P` from `isYes a?` by
-- unification. This is useful when we are using the decision procedure
-- for proof automation.
isYes : Dec A → Bool
isYes (true because _) = true
isYes (false because _) = false
isNo : Dec A → Bool
isNo = not ∘ isYes
True : Dec A → Set
True = T ∘ isYes
False : Dec A → Set
False = T ∘ isNo
-- The traditional name for isYes is ⌊_⌋, indicating the stripping of evidence.
⌊_⌋ = isYes
------------------------------------------------------------------------
-- Witnesses
-- Gives a witness to the "truth".
toWitness : {a? : Dec A} → True a? → A
toWitness {a? = true because [a]} _ = invert [a]
toWitness {a? = false because _ } ()
-- Establishes a "truth", given a witness.
fromWitness : {a? : Dec A} → A → True a?
fromWitness {a? = true because _ } = const _
fromWitness {a? = false because [¬a]} = invert [¬a]
-- Variants for False.
toWitnessFalse : {a? : Dec A} → False a? → ¬ A
toWitnessFalse {a? = true because _ } ()
toWitnessFalse {a? = false because [¬a]} _ = invert [¬a]
fromWitnessFalse : {a? : Dec A} → ¬ A → False a?
fromWitnessFalse {a? = true because [a]} = flip _$_ (invert [a])
fromWitnessFalse {a? = false because _ } = const _
-- If a decision procedure returns "yes", then we can extract the
-- proof using from-yes.
from-yes : (a? : Dec A) → From-yes a?
from-yes (true because [a]) = invert [a]
from-yes (false because _ ) = _
-- If a decision procedure returns "no", then we can extract the proof
-- using from-no.
from-no : (a? : Dec A) → From-no a?
from-no (false because [¬a]) = invert [¬a]
from-no (true because _ ) = _
------------------------------------------------------------------------
-- Maps
map′ : (A → B) → (B → A) → Dec A → Dec B
does (map′ A→B B→A a?) = does a?
proof (map′ A→B B→A (true because [a])) = of (A→B (invert [a]))
proof (map′ A→B B→A (false because [¬a])) = of (invert [¬a] ∘ B→A)
------------------------------------------------------------------------
-- Relationship with double-negation
-- Decidable predicates are stable.
decidable-stable : Dec A → Stable A
decidable-stable (true because [a]) ¬¬a = invert [a]
decidable-stable (false because [¬a]) ¬¬a = contradiction (invert [¬a]) ¬¬a
¬-drop-Dec : Dec (¬ ¬ A) → Dec (¬ A)
¬-drop-Dec ¬¬a? = map′ negated-stable contradiction (¬? ¬¬a?)
-- A double-negation-translated variant of excluded middle (or: every
-- nullary relation is decidable in the double-negation monad).
¬¬-excluded-middle : DoubleNegation (Dec A)
¬¬-excluded-middle ¬?a = ¬?a (no (λ a → ¬?a (yes a)))
------------------------------------------------------------------------
-- DEPRECATED NAMES
------------------------------------------------------------------------
-- Please use the new names as continuing support for the old names is
-- not guaranteed.
-- Version 2.0
excluded-middle = ¬¬-excluded-middle
{-# WARNING_ON_USAGE excluded-middle
"Warning: excluded-middle was deprecated in v2.0.
Please use ¬¬-excluded-middle instead."
#-}