-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBool.fm
158 lines (136 loc) · 3.2 KB
/
Bool.fm
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
// Bool.fm
// =======
//
// A Bool represents a binary logical truth-value, i.e.,
// it can be either true or false.
import Empty
import Equal
import Pair
import Unit
import Subset
// Definition
// ----------
T Bool
| true
| false
// Operations
// ----------
// Since bool is a finite datatype, it can be copied freely
// this function will be implicitly auto-generated in a
// future version of Formality
copy_bool(b : Bool) : Pair(Bool, Bool)
case b
| true => pair(__ true, true)
| false => pair(__ false, false)
// Negation
not(b: Bool) : Bool
case b
| true => false
| false => true
// Conjunction
and(a: Bool, b: Bool) : Bool
case a
| true => b
| false => false
// Disjuction
or(a: Bool, b: Bool) : Bool
case a
| true => true
| false => b
// Conjuction complement
nand(a: Bool, b: Bool) : Bool
case a
| true => not(b)
| false => true
// Disjunction complement
nor(a: Bool, b: Bool) : Bool
case a
| true => false
| false => not(b)
// Exclusive or
xor(a: Bool, b: Bool) : Bool
case a
with b : Bool
| true => not(b)
| false => b
// Logical equality
xnor(a: Bool, b: Bool) : Bool
case a
with b : Bool
| true => b
| false => not(b)
// not, with runtime fusion
not_f(b: Bool) : Bool
new(Bool) (P; true, false) =>
case b
| true => false
| false => true
: P(not_f(b))
// Number conversions
is_true(bool: Bool) : Number
case bool
| true => 1
| false => 0
is_false(bool: Bool) : Number
case bool
| true => 0
| false => 1
number_to_bool(n: Number)
if n then
true
else
false
// Theorems
// --------
// From `true == false` we can derive `Empty`. Proof:
// 1. Define a predicate `P` such that:
// - `P(true)` returns Unit
// - `P(false)` returns Empty
// 2. Note that `unit :: P(true)`
// 3. But `true == false`, so `unit :: P(false)`
// 4. Thus, `unit :: Empty`
true_isnt_false : true != false
let P = (x: Bool) =>
case x
| true => Unit
| false => Empty
(e) => unit :: rewrite P(.) with e
// The symmetry of true_isnt_false
false_isnt_true : false != true
let P = (x: Bool) =>
case x
| true => Empty
| false => Unit
(e) => unit :: rewrite P(.) with e
// A bool that is provably different from the input
different_elem(a : Bool) : Subset(Bool, (b) => a != b)
case a
| true => subset(_ (b) => ? != b; ?, true_isnt_false;)
| false => subset(_ (b) => ? != b; ?, false_isnt_true;)
: Subset(Bool, (b) => a != b)
// Demorgan's Law: !(a || b) == !a && !b
demorgan_0(a, b) : not(or(a,b)) == and(not(a),not(b))
case a
with b : Bool
| true => case b
| true => equal(__)
| false => equal(__)
: not(or(true,b)) == and(not(true), not(b))
| false => case b
| true => equal(__)
| false => equal(__)
: not(or(false,b)) == and(not(false), not(b))
: not(or(a,b)) == and(not(a), not(b))
// Demorgan's Law: !(a && b) == !a || !b
demorgan_1(a, b) : not(and(a,b)) == or(not(a), not(b))
case a
with b : Bool
| true => case b
| true => equal(__)
| false => equal(__)
: not(and(true,b)) == or(not(true), not(b))
| false => case b
| true => equal(__)
| false => equal(__)
: not(and(false,b)) == or(not(false), not(b))
: not(and(a,b)) == or(not(a), not(b))