1 package a
2
3 import "fmt"
4
5 type ImplicitOrd interface {
6 ~int | ~int8 | ~int16 | ~int32 | ~int64 |
7 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
8 ~float32 | ~float64 |
9 ~string
10 }
11
12 func LessGiven[T ImplicitOrd]() Ord[T] {
13 return LessFunc[T](func(a, b T) bool {
14 return a < b
15 })
16 }
17
18 type Eq[T any] interface {
19 Eqv(a T, b T) bool
20 }
21
22 type Ord[T any] interface {
23 Eq[T]
24 Less(a T, b T) bool
25 }
26
27 type LessFunc[T any] func(a, b T) bool
28
29 func (r LessFunc[T]) Eqv(a, b T) bool {
30 return r(a, b) == false && r(b, a) == false
31 }
32
33 func (r LessFunc[T]) Less(a, b T) bool {
34 return r(a, b)
35 }
36
37 type Option[T any] struct {
38 v *T
39 }
40
41 func (r Option[T]) IsDefined() bool {
42 return r.v != nil
43 }
44
45 func (r Option[T]) IsEmpty() bool {
46 return !r.IsDefined()
47 }
48
49 func (r Option[T]) Get() T {
50 return *r.v
51 }
52
53 func (r Option[T]) String() string {
54 if r.IsDefined() {
55 return fmt.Sprintf("Some(%v)", r.v)
56 } else {
57 return "None"
58 }
59 }
60
61 func (r Option[T]) OrElse(t T) T {
62 if r.IsDefined() {
63 return *r.v
64 }
65 return t
66 }
67
68 func (r Option[T]) Recover(f func() T) Option[T] {
69 if r.IsDefined() {
70 return r
71 }
72 t := f()
73 return Option[T]{&t}
74 }
75
76 type Func1[A1, R any] func(a1 A1) R
77
78 type Func2[A1, A2, R any] func(a1 A1, a2 A2) R
79
80 func (r Func2[A1, A2, R]) Curried() Func1[A1, Func1[A2, R]] {
81 return func(a1 A1) Func1[A2, R] {
82 return Func1[A2, R](func(a2 A2) R {
83 return r(a1, a2)
84 })
85 }
86 }
87
88 type HList interface {
89 sealed()
90 }
91
92
93 type Header[HT any] interface {
94 HList
95 Head() HT
96 }
97
98
99
100
101 type Cons[H any, T HList] interface {
102 HList
103 Head() H
104 Tail() T
105 }
106
107 type Nil struct {
108 }
109
110 func (r Nil) Head() Nil {
111 return r
112 }
113
114 func (r Nil) Tail() Nil {
115 return r
116 }
117
118 func (r Nil) String() string {
119 return "Nil"
120 }
121
122 func (r Nil) sealed() {
123
124 }
125
126 type hlistImpl[H any, T HList] struct {
127 head H
128 tail T
129 }
130
131 func (r hlistImpl[H, T]) Head() H {
132 return r.head
133 }
134
135 func (r hlistImpl[H, T]) Tail() T {
136 return r.tail
137 }
138
139 func (r hlistImpl[H, T]) String() string {
140 return fmt.Sprintf("%v :: %v", r.head, r.tail)
141 }
142
143 func (r hlistImpl[H, T]) sealed() {
144
145 }
146
147 func hlist[H any, T HList](h H, t T) Cons[H, T] {
148 return hlistImpl[H, T]{h, t}
149 }
150
151 func Concat[H any, T HList](h H, t T) Cons[H, T] {
152 return hlist(h, t)
153 }
154
155 func Empty() Nil {
156 return Nil{}
157 }
158 func Some[T any](v T) Option[T] {
159 return Option[T]{}.Recover(func() T {
160 return v
161 })
162 }
163
164 func None[T any]() Option[T] {
165 return Option[T]{}
166 }
167
168 func Ap[T, U any](t Option[Func1[T, U]], a Option[T]) Option[U] {
169 return FlatMap(t, func(f Func1[T, U]) Option[U] {
170 return Map(a, f)
171 })
172 }
173
174 func Map[T, U any](opt Option[T], f func(v T) U) Option[U] {
175 return FlatMap(opt, func(v T) Option[U] {
176 return Some(f(v))
177 })
178 }
179
180 func FlatMap[T, U any](opt Option[T], fn func(v T) Option[U]) Option[U] {
181 if opt.IsDefined() {
182 return fn(opt.Get())
183 }
184 return None[U]()
185 }
186
187 type ApplicativeFunctor1[H Header[HT], HT, A, R any] struct {
188 h Option[H]
189 fn Option[Func1[A, R]]
190 }
191
192 func (r ApplicativeFunctor1[H, HT, A, R]) ApOption(a Option[A]) Option[R] {
193 return Ap(r.fn, a)
194 }
195
196 func (r ApplicativeFunctor1[H, HT, A, R]) Ap(a A) Option[R] {
197 return r.ApOption(Some(a))
198 }
199
200 func Applicative1[A, R any](fn Func1[A, R]) ApplicativeFunctor1[Nil, Nil, A, R] {
201 return ApplicativeFunctor1[Nil, Nil, A, R]{Some(Empty()), Some(fn)}
202 }
203
204 type ApplicativeFunctor2[H Header[HT], HT, A1, A2, R any] struct {
205 h Option[H]
206 fn Option[Func1[A1, Func1[A2, R]]]
207 }
208
209 func (r ApplicativeFunctor2[H, HT, A1, A2, R]) ApOption(a Option[A1]) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
210
211 nh := FlatMap(r.h, func(hv H) Option[Cons[A1, H]] {
212 return Map(a, func(av A1) Cons[A1, H] {
213 return Concat(av, hv)
214 })
215 })
216
217 return ApplicativeFunctor1[Cons[A1, H], A1, A2, R]{nh, Ap(r.fn, a)}
218 }
219 func (r ApplicativeFunctor2[H, HT, A1, A2, R]) Ap(a A1) ApplicativeFunctor1[Cons[A1, H], A1, A2, R] {
220
221 return r.ApOption(Some(a))
222 }
223
224 func Applicative2[A1, A2, R any](fn Func2[A1, A2, R]) ApplicativeFunctor2[Nil, Nil, A1, A2, R] {
225 return ApplicativeFunctor2[Nil, Nil, A1, A2, R]{Some(Empty()), Some(fn.Curried())}
226 }
227 func OrdOption[T any](m Ord[T]) Ord[Option[T]] {
228 return LessFunc[Option[T]](func(t1 Option[T], t2 Option[T]) bool {
229 if !t1.IsDefined() && !t2.IsDefined() {
230 return false
231 }
232 return Applicative2(m.Less).ApOption(t1).ApOption(t2).OrElse(!t1.IsDefined())
233 })
234 }
235
236 func Given[T ImplicitOrd]() Ord[T] {
237 return LessGiven[T]()
238 }
239
View as plain text