-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsubtyping.go
96 lines (76 loc) · 1.55 KB
/
subtyping.go
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
package main
import "fmt"
/*
Eq : T ⟼ T ⟼ bool
Each type implements own equality, mapping pair of value to bool category
*/
type Eq[T any] interface {
Equal(T, T) bool
}
/*
Ord : T ⟼ T ⟼ Ordering
Each type implements compare rules, mapping pair of value to enum{ LT, EQ, GT }
*/
type Ord[T any] interface {
Eq[T]
Compare(T, T) Ordering
}
// Ordering type defines enum{ LT, EQ, GT }
type Ordering int
// enum{ LT, EQ, GT }
const (
LT Ordering = -1
EQ Ordering = 0
GT Ordering = 1
)
type ordInt string
func (ord ordInt) Equal(a, b int) bool {
return ord.Compare(a, b) == EQ
}
func (ordInt) Compare(a, b int) Ordering {
switch {
case a < b:
return LT
case a > b:
return GT
default:
return EQ
}
}
/*
Int create a new instance of Eq trait for int domain as immutable value so that
other functions can use this constant like `eq.Int.Eq(...)`
*/
const Int = ordInt("ord.int")
/*
Searcher is an example of algorithms that uses sub-typing
*/
type Searcher[T any] struct{ Ord[T] }
func (s Searcher[T]) Lookup(e T, seq []T) {
l := 0
r := len(seq) - 1
next:
for {
if r >= l {
m := l + (r-l)/2
switch s.Ord.Compare(seq[m], e) {
case EQ:
fmt.Printf("%v found at %v in %v\n", e, m, seq)
return
case LT:
l = m + 1
continue next
case GT:
r = m - 1
continue next
}
}
fmt.Printf("%v is not found in %v\n", e, seq)
return
}
}
func main() {
searcher := Searcher[int]{Int}
searcher.Lookup(23, []int{2, 5, 8, 12, 16, 23, 38, 56, 72, 91})
searcher.Lookup(40, []int{2, 5, 8, 12, 16, 23, 38, 56, 72, 91})
}