-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPreorder.lidr
177 lines (127 loc) · 4.71 KB
/
Preorder.lidr
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
> module Preorder
> import Prop
> import Syntax.PreorderReasoning
> %default total
> %auto_implicits off
> %access public export
Preorders, partial orders, linear orders
========================================
Relations
---------
A binary relation between types X and Y is a "subset" of the cartesian
product XxY. How to model this?
First attempt:
--------------
as a boolean predicate in "curried" form:
> RelB : Type -> Type -> Type
> RelB A B = A -> B -> Bool
binary relations on A then become
> BinRelB : Type -> Type
> BinRelB A = RelB A A
Examples
the empty relation between any two types
> emptyRelB : {A, B : Type} -> RelB A B
> emptyRelB x y = False
and the "all" relation:
> allRelB : {A, B : Type} -> RelB A B
> allRelB x y = True
"normal" greater or equal on Nat:
> geq : BinRelB Nat
> geq Z Z = True
> geq Z (S n) = True
> geq (S m) Z = False
> geq (S m) (S n) = geq m n
prefix order on lists
(we need the element type to have a decidable equality)
< lPre : DecEq a => BinRelB (List a)
< lPre [] _ = True
< lPre (x::xs) [] = False
< lPre (x::xs) (y::ys)
< with (decEq x y)
< | Yes _ = lPre xs ys
< | No _ = False
But properties of relations are difficult to implement, e.g.:
< isReflexiveB : {A : Type} -> BinRelB A -> Bool
if A is infinite, such a "check" for reflexivity will never finish,
so we cannot implement this as a total function! So
Second attempt
--------------
as a type valued function!
> Rel : Type -> Type -> Type
> Rel A B = A -> B -> Type
A relation r in (Rel A B) is a "family" of types, one
for each pair of elements a in A and b in B. Elements of
this type r a b are the proves (evidences, witnesses, ...) that
a and b are in relation r.
the empty relation between any two types
> emptyRel : {A, B : Type} -> Rel A B
> emptyRel x y = Void
the "all" relation:
> allRel : {A, B : Type} -> Rel A B
> allRel x y = ()
> BinRel : Type -> Type
> BinRel A = Rel A A
> data IsRefl : {A : Type} -> BinRel A -> Type where
> PrfRefl : -- if for a relation r on A
> {A : Type} -> {r : BinRel A} ->
> -- we provide for each x in A an element of (r x x)
> ( (x : A) -> r x x ) ->
> -- then we have proved reflexivity of r
> (IsRefl r)
> data IsTrans : {A : Type} -> BinRel A -> Type where
> PrfTrans : -- if for a relation r on A
> {A : Type} -> {r : BinRel A} ->
> -- for any x,y,z in A, given proofs (r x y) and (r y z)
> -- we can produce a proof of (r x z)
> ({x, y, z : A} -> r x y -> r y z -> r x z ) ->
> -- then we have proved transitivity of r
> (IsTrans r)
Preorder
--------
To model a preordered set:
> data Preorder : Type where
> MkPreorder : {- the set is modeled as a type -}
> (O : Type) ->
> {- the fact "a R b" is also modeled by a type -}
> (R : O -> O -> Type) ->
> {- R is reflexive -}
> (Ref : (a : O) -> R a a) ->
> {- R is transitive -}
> (Trans : {a, b, c : O} ->
> R a b -> R b c -> R a c) ->
> {- the types "a R b" have at most one inhabitant,
> i.e. they are "Propositions" -}
> (IsPropR : {a, b : O} -> IsProp (R a b)) ->
> Preorder
> PObj : Preorder -> Type
> PObj (MkPreorder o _ _ _ _) = o
> PHom : (pp : Preorder) -> (PObj pp) -> (PObj pp) -> Type
> PHom (MkPreorder _ rel _ _ _) = rel
> PRefl : {pp : Preorder} -> (a : PObj pp) -> PHom pp a a
> PRefl {pp=(MkPreorder _ _ ref _ _)} = ref
> PTrans : {pp : Preorder} -> {a, b, c : PObj pp} ->
> (PHom pp a b) -> (PHom pp b c) -> (PHom pp a c)
> PTrans {pp=(MkPreorder _ _ _ trans _)} = trans
> PProp : {pp : Preorder} -> {a, b : PObj pp} ->
> IsProp ( PHom pp a b )
> PProp {pp=(MkPreorder _ _ _ _ isProp)} = isProp
> namespace Preorder
> using (pp : Preorder, a : PObj pp, b: PObj pp, c : PObj pp)
> qed : (a : PObj pp) -> PHom pp a a
> qed = PRefl
> step : (a : PObj pp) -> PHom pp a b -> PHom pp b c -> PHom pp a c
> step a p q = PTrans p q
> isTrans' : (pp : Preorder) -> (a, b, c : PObj pp) ->
> (PHom pp a b) -> (PHom pp b c) -> (PHom pp a c)
> isTrans' pp a b c p q =
> a ={ p }=
> b ={ q }=
> c QED
Meets
> data IsMeet : {pp : Preorder} -> (a, b, c : PObj pp) -> Type where
> PrfIsMeet : {pp : Preorder} -> (a, b, c : PObj pp) ->
> -- c is lower bound of {a,b}
> (PHom pp c a) -> (PHom pp c b) ->
> -- and for any other lower bound d, d is lower than c
> ((d : PObj pp) -> PHom pp d a -> PHom pp d b -> PHom pp d c) ->
> IsMeet a b c