mayak 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,619 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Mayak
5
+ module Monads
6
+ module Try
7
+ extend T::Sig
8
+ extend T::Generic
9
+
10
+ abstract!
11
+ sealed!
12
+
13
+ Value = type_member
14
+
15
+ sig {
16
+ abstract
17
+ .type_parameters(:NewValue)
18
+ .params(blk: T.proc.params(arg0: Value).returns(T.type_parameter(:NewValue)))
19
+ .returns(Try[T.type_parameter(:NewValue)])
20
+ }
21
+ def map(&blk)
22
+ end
23
+
24
+ sig {
25
+ abstract
26
+ .type_parameters(:NewValue)
27
+ .params(
28
+ blk: T.proc.params(arg0: Value).returns(Try[T.type_parameter(:NewValue)])
29
+ )
30
+ .returns(Try[T.type_parameter(:NewValue)])
31
+ }
32
+ def flat_map(&blk)
33
+ end
34
+
35
+ sig {
36
+ abstract
37
+ .params(error: StandardError, blk: T.proc.params(arg0: Value).returns(T::Boolean))
38
+ .returns(Try[Value])
39
+ }
40
+ def filter_or(error, &blk)
41
+ end
42
+
43
+ sig { abstract.returns(T::Boolean) }
44
+ def success?
45
+ end
46
+
47
+ sig { abstract.returns(T::Boolean) }
48
+ def failure?
49
+ end
50
+
51
+ sig { abstract.params(value: Value).returns(Value) }
52
+ def success_or(value)
53
+ end
54
+
55
+ sig { abstract.params(value: StandardError).returns(StandardError) }
56
+ def failure_or(value)
57
+ end
58
+
59
+ sig {
60
+ abstract
61
+ .type_parameters(:Result)
62
+ .params(
63
+ failure_branch: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Result)),
64
+ success_branch: T.proc.params(arg0: Value).returns(T.type_parameter(:Result))
65
+ ).returns(
66
+ T.type_parameter(:Result)
67
+ )
68
+ }
69
+ def either(failure_branch, success_branch)
70
+ end
71
+
72
+ sig {
73
+ abstract
74
+ .params(blk: T.proc.params(arg0: Value).void)
75
+ .returns(Try[Value])
76
+ }
77
+ def tee(&blk)
78
+ end
79
+
80
+ sig {
81
+ abstract
82
+ .params(blk: T.proc.params(arg0: StandardError).returns(StandardError))
83
+ .returns(Try[Value])
84
+ }
85
+ def map_failure(&blk)
86
+ end
87
+
88
+ sig {
89
+ abstract
90
+ .params(blk: T.proc.params(arg0: StandardError).returns(Try[Value]))
91
+ .returns(Try[Value])
92
+ }
93
+ def flat_map_failure(&blk)
94
+ end
95
+
96
+ sig {
97
+ abstract
98
+ .type_parameters(:Failure)
99
+ .params(blk: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Failure)))
100
+ .returns(Mayak::Monads::Result[T.type_parameter(:Failure), Value])
101
+ }
102
+ def to_result(&blk)
103
+ end
104
+
105
+ sig { abstract.returns(Mayak::Monads::Maybe[Value]) }
106
+ def to_maybe
107
+ end
108
+
109
+ sig(:final) { params(other: Mayak::Monads::Try[T.untyped]).returns(T::Boolean) }
110
+ def ==(other)
111
+ case self
112
+ when Mayak::Monads::Try::Success
113
+ case other
114
+ when Mayak::Monads::Try::Success then T.unsafe(success) == other.success
115
+ when Mayak::Monads::Try::Failure then false
116
+ else T.absurd(other)
117
+ end
118
+ when Mayak::Monads::Try::Failure
119
+ case other
120
+ when Mayak::Monads::Try::Success then false
121
+ when Mayak::Monads::Try::Failure then T.unsafe(failure) == other.failure
122
+ else T.absurd(other)
123
+ end
124
+ else
125
+ T.absurd(self)
126
+ end
127
+ end
128
+
129
+ sig(:final) {
130
+ type_parameters(:NewValue)
131
+ .params(new_value: T.type_parameter(:NewValue))
132
+ .returns(Try[T.type_parameter(:NewValue)])
133
+ }
134
+ def as(new_value)
135
+ map { |_| new_value }
136
+ end
137
+
138
+ sig(:final) { params(new_failure: StandardError).returns(Try[Value]) }
139
+ def failure_as(new_failure)
140
+ map_failure { |_| new_failure }
141
+ end
142
+
143
+ sig {
144
+ abstract
145
+ .params(value: Value)
146
+ .returns(Try[Value])
147
+ }
148
+ def recover(value)
149
+ end
150
+
151
+ sig {
152
+ abstract
153
+ .params(blk: T.proc.params(arg0: StandardError).returns(Value))
154
+ .returns(Try[Value])
155
+ }
156
+ def recover_with(&blk)
157
+ end
158
+
159
+ sig {
160
+ abstract
161
+ .params(
162
+ error_type: T.class_of(StandardError),
163
+ blk: T.proc.params(arg0: StandardError).returns(Value)
164
+ )
165
+ .returns(Try[Value])
166
+ }
167
+ def recover_on(error_type, &blk)
168
+ end
169
+
170
+ sig(:final) {
171
+ params(blk: T.proc.params(arg0: StandardError).returns(Try[Value])).returns(Try[Value])
172
+ }
173
+ def recover_with_try(&blk)
174
+ flat_map_failure(&blk)
175
+ end
176
+
177
+ sig {
178
+ type_parameters(:Value)
179
+ .params(results: T::Array[Mayak::Monads::Try[T.type_parameter(:Value)]])
180
+ .returns(Mayak::Monads::Try[T::Array[T.type_parameter(:Value)]])
181
+ }
182
+ def self.sequence(results)
183
+ init = T.let(Try::Success.new([]), Try[T::Array[T.type_parameter(:Value)]])
184
+ results.reduce(init) do |result, element|
185
+ result.flat_map do |array|
186
+ element.map { |value| array + [value] }
187
+ end
188
+ end
189
+ end
190
+
191
+ sig {
192
+ type_parameters(:Value)
193
+ .params(
194
+ value: T.type_parameter(:Value),
195
+ error: StandardError,
196
+ blk: T.proc.returns(T::Boolean)
197
+ ).returns(Mayak::Monads::Try[T.type_parameter(:Value)])
198
+ }
199
+ def self.check(value, error, &blk)
200
+ if blk.call
201
+ Mayak::Monads::Try::Success[T.type_parameter(:Value)].new(value)
202
+ else
203
+ Mayak::Monads::Try::Failure[T.type_parameter(:Value)].new(error)
204
+ end
205
+ end
206
+
207
+ sig { params(error: StandardError, blk: T.proc.returns(T::Boolean)).returns(Mayak::Monads::Try[NilClass]) }
208
+ def self.guard(error, &blk)
209
+ check(nil, error, &blk)
210
+ end
211
+
212
+ class Success
213
+ extend T::Sig
214
+ extend T::Generic
215
+
216
+ final!
217
+
218
+ Value = type_member
219
+
220
+ include Mayak::Monads::Try
221
+
222
+ sig(:final) { params(value: Value).void }
223
+ def initialize(value)
224
+ @value = T.let(value, Value)
225
+ end
226
+
227
+ sig(:final) {
228
+ override
229
+ .type_parameters(:NewValue)
230
+ .params(blk: T.proc.params(arg0: Value).returns(T.type_parameter(:NewValue)))
231
+ .returns(Try[T.type_parameter(:NewValue)])
232
+ }
233
+ def map(&blk)
234
+ Mayak::Monads::Try::Success.new(blk.call(@value))
235
+ end
236
+
237
+ sig(:final) {
238
+ override
239
+ .type_parameters(:NewValue)
240
+ .params(blk: T.proc.params(arg0: Value).returns(Try[T.type_parameter(:NewValue)]))
241
+ .returns(Try[T.type_parameter(:NewValue)])
242
+ }
243
+ def flat_map(&blk)
244
+ blk.call(@value)
245
+ end
246
+
247
+ sig(:final) {
248
+ override
249
+ .params(error: StandardError, blk: T.proc.params(arg0: Value).returns(T::Boolean))
250
+ .returns(Try[Value])
251
+ }
252
+ def filter_or(error, &blk)
253
+ if blk.call(@value)
254
+ self
255
+ else
256
+ Mayak::Monads::Try::Failure[Value].new(error)
257
+ end
258
+ end
259
+
260
+ sig(:final) { returns(Value) }
261
+ def success
262
+ @value
263
+ end
264
+
265
+ sig(:final) { override.returns(T::Boolean) }
266
+ def success?
267
+ true
268
+ end
269
+
270
+ sig(:final) { override.returns(T::Boolean) }
271
+ def failure?
272
+ false
273
+ end
274
+
275
+ sig(:final) { override.params(value: Value).returns(Value) }
276
+ def success_or(value)
277
+ @value
278
+ end
279
+
280
+ sig(:final) { override.params(value: StandardError).returns(StandardError) }
281
+ def failure_or(value)
282
+ value
283
+ end
284
+
285
+ sig(:final) {
286
+ override
287
+ .type_parameters(:Result)
288
+ .params(
289
+ failure_branch: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Result)),
290
+ success_branch: T.proc.params(arg0: Value).returns(T.type_parameter(:Result))
291
+ ).returns(
292
+ T.type_parameter(:Result)
293
+ )
294
+ }
295
+ def either(failure_branch, success_branch)
296
+ success_branch.call(@value)
297
+ end
298
+
299
+ sig(:final) {
300
+ override
301
+ .params(blk: T.proc.params(arg0: Value).void)
302
+ .returns(Try[Value])
303
+ }
304
+ def tee(&blk)
305
+ blk.call(@value)
306
+ self
307
+ end
308
+
309
+ sig(:final) {
310
+ override
311
+ .params(blk: T.proc.params(arg0: StandardError).returns(StandardError))
312
+ .returns(Try[Value])
313
+ }
314
+ def map_failure(&blk)
315
+ self
316
+ end
317
+
318
+ sig(:final) {
319
+ override
320
+ .params(blk: T.proc.params(arg0: StandardError).returns(Try[Value]))
321
+ .returns(Try[Value])
322
+ }
323
+ def flat_map_failure(&blk)
324
+ self
325
+ end
326
+
327
+ sig(:final) {
328
+ override
329
+ .type_parameters(:Failure)
330
+ .params(blk: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Failure)))
331
+ .returns(Mayak::Monads::Result[T.type_parameter(:Failure), Value])
332
+ }
333
+ def to_result(&blk)
334
+ Mayak::Monads::Result::Success.new(@value)
335
+ end
336
+
337
+ sig(:final) { override.returns(Mayak::Monads::Maybe[Value]) }
338
+ def to_maybe
339
+ Mayak::Monads::Maybe::Some.new(@value)
340
+ end
341
+
342
+ sig(:final) {
343
+ override
344
+ .params(
345
+ error_type: T.class_of(StandardError),
346
+ blk: T.proc.params(arg0: StandardError).returns(Value)
347
+ )
348
+ .returns(Try[Value])
349
+ }
350
+ def recover_on(error_type, &blk)
351
+ self
352
+ end
353
+
354
+ sig(:final) {
355
+ override
356
+ .params(value: Value)
357
+ .returns(Try[Value])
358
+ }
359
+ def recover(value)
360
+ self
361
+ end
362
+
363
+ sig(:final) { override.params(blk: T.proc.params(arg0: StandardError).returns(Value)).returns(Try[Value]) }
364
+ def recover_with(&blk)
365
+ self
366
+ end
367
+ end
368
+
369
+ class Failure
370
+ extend T::Sig
371
+ extend T::Generic
372
+
373
+ final!
374
+
375
+ Value = type_member
376
+
377
+ include Mayak::Monads::Try
378
+
379
+ sig(:final) { params(value: StandardError).void }
380
+ def initialize(value)
381
+ @failure = T.let(value, StandardError)
382
+ end
383
+
384
+ sig(:final) {
385
+ override
386
+ .type_parameters(:NewValue)
387
+ .params(blk: T.proc.params(arg0: Value).returns(T.type_parameter(:NewValue)))
388
+ .returns(Try[T.type_parameter(:NewValue)])
389
+ }
390
+ def map(&blk)
391
+ T.cast(
392
+ self,
393
+ Try[T.type_parameter(:NewValue)]
394
+ )
395
+ end
396
+
397
+ sig(:final) {
398
+ override
399
+ .type_parameters(:NewValue)
400
+ .params(blk: T.proc.params(arg0: Value).returns(Try[T.type_parameter(:NewValue)]))
401
+ .returns(Try[T.type_parameter(:NewValue)])
402
+ }
403
+ def flat_map(&blk)
404
+ T.cast(
405
+ self,
406
+ Try[T.type_parameter(:NewValue)]
407
+ )
408
+ end
409
+
410
+ sig(:final) {
411
+ override
412
+ .params(error: StandardError, blk: T.proc.params(arg0: Value).returns(T::Boolean))
413
+ .returns(Try[Value])
414
+ }
415
+ def filter_or(error, &blk)
416
+ self
417
+ end
418
+
419
+ sig(:final) { returns(StandardError) }
420
+ def failure
421
+ @failure
422
+ end
423
+
424
+ sig(:final) { override.returns(T::Boolean) }
425
+ def success?
426
+ false
427
+ end
428
+
429
+ sig(:final) { override.returns(T::Boolean) }
430
+ def failure?
431
+ true
432
+ end
433
+
434
+ sig(:final) { override.params(value: Value).returns(Value) }
435
+ def success_or(value)
436
+ value
437
+ end
438
+
439
+ sig(:final) { override.params(value: StandardError).returns(StandardError) }
440
+ def failure_or(value)
441
+ @failure
442
+ end
443
+
444
+ sig(:final) {
445
+ override
446
+ .type_parameters(:Result)
447
+ .params(
448
+ failure_branch: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Result)),
449
+ success_branch: T.proc.params(arg0: Value).returns(T.type_parameter(:Result))
450
+ ).returns(
451
+ T.type_parameter(:Result)
452
+ )
453
+ }
454
+ def either(failure_branch, success_branch)
455
+ failure_branch.call(@failure)
456
+ end
457
+
458
+ sig(:final) {
459
+ override
460
+ .params(blk: T.proc.params(arg0: Value).void)
461
+ .returns(Try[Value])
462
+ }
463
+ def tee(&blk)
464
+ self
465
+ end
466
+
467
+ sig(:final) {
468
+ override
469
+ .params(blk: T.proc.params(arg0: StandardError).returns(StandardError))
470
+ .returns(Try[Value])
471
+ }
472
+ def map_failure(&blk)
473
+ Mayak::Monads::Try::Failure[Value].new(blk.call(@failure))
474
+ end
475
+
476
+ sig(:final) {
477
+ override
478
+ .params(blk: T.proc.params(arg0: StandardError).returns(Try[Value]))
479
+ .returns(Try[Value])
480
+ }
481
+ def flat_map_failure(&blk)
482
+ blk.call(@failure)
483
+ end
484
+
485
+ sig(:final) {
486
+ override
487
+ .type_parameters(:Failure)
488
+ .params(blk: T.proc.params(arg0: StandardError).returns(T.type_parameter(:Failure)))
489
+ .returns(Mayak::Monads::Result[T.type_parameter(:Failure), Value])
490
+ }
491
+ def to_result(&blk)
492
+ Mayak::Monads::Result::Failure.new(blk.call(@failure))
493
+ end
494
+
495
+ sig(:final) { override.returns(Mayak::Monads::Maybe[Value]) }
496
+ def to_maybe
497
+ Mayak::Monads::Maybe::None.new
498
+ end
499
+
500
+ sig(:final) {
501
+ override
502
+ .params(
503
+ error_type: T.class_of(StandardError),
504
+ blk: T.proc.params(arg0: StandardError).returns(Value)
505
+ )
506
+ .returns(Try[Value])
507
+ }
508
+ def recover_on(error_type, &blk)
509
+ if @failure.is_a?(error_type)
510
+ Mayak::Monads::Try::Success[Value].new(blk.call(@failure))
511
+ else
512
+ self
513
+ end
514
+ end
515
+
516
+ sig(:final) {
517
+ override
518
+ .params(value: Value)
519
+ .returns(Try[Value])
520
+ }
521
+ def recover(value)
522
+ Mayak::Monads::Try::Success[Value].new(value)
523
+ end
524
+
525
+ sig(:final) { override.params(blk: T.proc.params(arg0: StandardError).returns(Value)).returns(Try[Value]) }
526
+ def recover_with(&blk)
527
+ Mayak::Monads::Try::Success[Value].new(blk.call(@failure))
528
+ end
529
+ end
530
+
531
+ module Mixin
532
+ extend T::Sig
533
+
534
+ include Kernel
535
+
536
+ sig {
537
+ type_parameters(:Value)
538
+ .params(
539
+ exception_classes: T.class_of(StandardError),
540
+ blk: T.proc.returns(T.type_parameter(:Value))
541
+ )
542
+ .returns(Try[T.type_parameter(:Value)])
543
+ }
544
+ def Try(*exception_classes, &blk)
545
+ exception_classes = [StandardError] if exception_classes.empty?
546
+ begin
547
+ Mayak::Monads::Try::Success[T.type_parameter(:Value)].new(blk.call)
548
+ rescue *exception_classes => e
549
+ Mayak::Monads::Try::Failure[T.type_parameter(:Value)].new(T.unsafe(e))
550
+ end
551
+ end
552
+
553
+ sig {
554
+ type_parameters(:Value)
555
+ .params(blk: T.proc.returns(T.type_parameter(:Value)))
556
+ .returns(Try[T.type_parameter(:Value)])
557
+ }
558
+ def for_try(&blk)
559
+ result = blk.call
560
+ Mayak::Monads::Try::Success[T.type_parameter(:Value)].new(result)
561
+ rescue Halt => e
562
+ e.result
563
+ end
564
+
565
+ sig {
566
+ type_parameters(:Value)
567
+ .params(value: Try[T.type_parameter(:Value)])
568
+ .returns(T.type_parameter(:Value))
569
+ }
570
+ def do_try!(value)
571
+ case value
572
+ when Mayak::Monads::Try::Success
573
+ value.success
574
+ when Mayak::Monads::Try::Failure
575
+ raise Halt[T.type_parameter(:Value)].new(value)
576
+ else
577
+ T.absurd(value)
578
+ end
579
+ end
580
+
581
+ sig {
582
+ type_parameters(:Value)
583
+ .params(
584
+ value: T.type_parameter(:Value),
585
+ error: StandardError,
586
+ blk: T.proc.returns(T::Boolean)
587
+ ).returns(T.type_parameter(:Value))
588
+ }
589
+ def check_try!(value, error, &blk)
590
+ do_try!(Mayak::Monads::Try.check(value, error, &blk))
591
+ end
592
+
593
+ sig { params(error: StandardError, blk: T.proc.returns(T::Boolean)).void }
594
+ def guard_try!(error, &blk)
595
+ do_try!(Mayak::Monads::Try.guard(error, &blk))
596
+ end
597
+
598
+ class Halt < StandardError
599
+ extend T::Sig
600
+ extend T::Generic
601
+ extend T::Helpers
602
+
603
+ SuccessType = type_member
604
+
605
+ sig { returns(Mayak::Monads::Try[SuccessType]) }
606
+ attr_reader :result
607
+
608
+ sig { params(result: Mayak::Monads::Try[SuccessType]).void }
609
+ def initialize(result)
610
+ super()
611
+
612
+ @result = T.let(result, Mayak::Monads::Try[SuccessType])
613
+ end
614
+ end
615
+ private_constant :Halt
616
+ end
617
+ end
618
+ end
619
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
4
+ module Mayak
5
+ module Numeric
6
+ extend T::Sig
7
+
8
+ sig { params(value: T.any(NilClass, String, BigDecimal, Integer, Float)).returns(Mayak::Monads::Maybe[Float]) }
9
+ def self.parse_float(value)
10
+ return Mayak::Monads::Maybe::None[Float].new if value.nil?
11
+
12
+ Mayak::Monads::Maybe::Some[Float].new(Float(value))
13
+ rescue ArgumentError, TypeError, FloatDomainError
14
+ Mayak::Monads::Maybe::None[Float].new
15
+ end
16
+
17
+ sig { params(value: T.any(NilClass, String, BigDecimal, Integer)).returns(Mayak::Monads::Maybe[Integer]) }
18
+ def self.parse_integer(value)
19
+ return Mayak::Monads::Maybe::None[Integer].new if value.nil?
20
+
21
+ Mayak::Monads::Maybe::Some[Integer].new(Integer(value))
22
+ rescue ArgumentError, TypeError
23
+ Mayak::Monads::Maybe::None[Integer].new
24
+ end
25
+
26
+ sig { params(value: T.any(NilClass, String, Integer, BigDecimal, Float)).returns(Mayak::Monads::Maybe[BigDecimal]) }
27
+ def self.parse_decimal(value)
28
+ return Mayak::Monads::Maybe::None[BigDecimal].new if value.nil?
29
+
30
+ case value
31
+ when String
32
+ Mayak::Monads::Maybe::Some[BigDecimal].new(BigDecimal(value))
33
+ when Integer
34
+ Mayak::Monads::Maybe::Some[BigDecimal].new(BigDecimal(value))
35
+ when BigDecimal
36
+ Mayak::Monads::Maybe::Some[BigDecimal].new(value)
37
+ when Float
38
+ Mayak::Monads::Maybe::Some[BigDecimal].new(value.to_d)
39
+ end
40
+ rescue ArgumentError, TypeError
41
+ Mayak::Monads::Maybe::None[BigDecimal].new
42
+ end
43
+ end
44
+ end