kind 2.0.0 → 2.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebd68f3e676f6b030fa85da36b57a47a7f866e52373aed2b0e41315c63b0fdd0
4
- data.tar.gz: 5800122e2ed54025450eabe06bee5f9df3474c45b6ffa396c3b80dc4ad8ca566
3
+ metadata.gz: a83d36b4c1fe131567251f418b775a8366ecf2a7c0d31682f801866cb9d83a27
4
+ data.tar.gz: b9b613500675aa1ea9e10c4b5ff83a451f289aec39896aaed025c196f0212ece
5
5
  SHA512:
6
- metadata.gz: d3769fbbe39073a41961af28fde90412f30f1caab3b2129b4a91a39afb1e482310e209b1a5eea4249f09c667760f862c06cc98dc56ab7bb40854561ef75ea435
7
- data.tar.gz: 8356c7a49afe6370ecced9485acd2a663d1f17729cbbccd89dec2c1f839ad0f754778502e447c89b8a129697a891bed07af30c20df0b52a9e4d338cb4df593ed
6
+ metadata.gz: 252e2e4f3bd9bbd09ff182579d450de170688ada607dfaa30cd70748c1ac4473381c856ba1be37f74ccd1eb05d077763cbf853ea1f356c58226408108e69f4e8
7
+ data.tar.gz: f35a606761e6de74f81427a4431c711252303f78e4b0b5d11dd5e1878180112c1733fa4fef85949f3414196e387b54c672e768384f92aff9ac1c434662529834
data/README.md CHANGED
@@ -18,11 +18,14 @@ One of the goals of this project is to do simple type checking like `"some strin
18
18
  - [Required Ruby version](#required-ruby-version)
19
19
  - [Installation](#installation)
20
20
  - [Usage](#usage)
21
- - [Verifying the kind of some object](#verifying-the-kind-of-some-object)
22
- - [Verifying the kind of some class/module](#verifying-the-kind-of-some-classmodule)
21
+ - [Kind.of.\<Type\>() - Verifying the kind of some object](#kindoftype---verifying-the-kind-of-some-object)
22
+ - [Method aliases to perform a strict validation](#method-aliases-to-perform-a-strict-validation)
23
+ - [Kind.of.\<Type\>.or_nil()](#kindoftypeor_nil)
24
+ - [Kind.of.\<Type\>.instance?()](#kindoftypeinstance)
25
+ - [Kind.is.\<Type\>() - Verifying if some class/module is the expected kind.](#kindistype---verifying-if-some-classmodule-is-the-expected-kind)
23
26
  - [How to create a new type checker?](#how-to-create-a-new-type-checker)
24
27
  - [Creating/Verifiyng type checkers dynamically](#creatingverifiyng-type-checkers-dynamically)
25
- - [Registering new (custom) type checkers](#registering-new-custom-type-checkers)
28
+ - [Registering new (custom) type checker](#registering-new-custom-type-checker)
26
29
  - [What happens if a custom type checker has a namespace?](#what-happens-if-a-custom-type-checker-has-a-namespace)
27
30
  - [Type checkers](#type-checkers)
28
31
  - [Classes' type checkers](#classes-type-checkers)
@@ -31,11 +34,15 @@ One of the goals of this project is to do simple type checking like `"some strin
31
34
  - [Kind::Undefined](#kindundefined)
32
35
  - [Kind.of.\<Type\>.or_undefined()](#kindoftypeor_undefined)
33
36
  - [Kind::Maybe](#kindmaybe)
34
- - [Kind::Maybe[] and Kind::Maybe#then](#kindmaybe-and-kindmaybethen)
35
- - [Kind::Maybe#try](#kindmaybetry)
37
+ - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas)
38
+ - [Kind::Maybe[] and Kind::Maybe#then method aliases](#kindmaybe-and-kindmaybethen-method-aliases)
39
+ - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-1)
40
+ - [Kind::None() and Kind::Some()](#kindnone-and-kindsome)
36
41
  - [Kind.of.Maybe()](#kindofmaybe)
37
42
  - [Kind::Optional](#kindoptional)
43
+ - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-2)
38
44
  - [Kind.of.\<Type\>.as_optional](#kindoftypeas_optional)
45
+ - [Kind::Maybe#try](#kindmaybetry)
39
46
  - [Kind::Validator (ActiveModel::Validations)](#kindvalidator-activemodelvalidations)
40
47
  - [Usage](#usage-1)
41
48
  - [Defining the default validation strategy](#defining-the-default-validation-strategy)
@@ -82,14 +89,14 @@ sum(1, 1) # 2
82
89
  sum('1', 1) # Kind::Error ("\"1\" expected to be a kind of Numeric")
83
90
  ```
84
91
 
85
- ### Verifying the kind of some object
92
+ ### Kind.of.\<Type\>() - Verifying the kind of some object
86
93
 
87
94
  By default, basic verifications are strict. So, when you perform `Kind.of.Hash(value)`, if the given value was a Hash, the value itself will be returned, but if it isn't the right type, an error will be raised.
88
95
 
89
96
  ```ruby
90
- Kind.of.Hash(nil) # **raise Kind::Error, "nil expected to be a kind of Hash"**
91
- Kind.of.Hash('') # raise Kind::Error, "'' expected to be a kind of Hash"
92
- Kind.of.Hash({a: 1}) # {a: 1}
97
+ Kind.of.Hash(nil) # **raise Kind::Error, "nil expected to be a kind of Hash"**
98
+ Kind.of.Hash('') # raise Kind::Error, "'' expected to be a kind of Hash"
99
+ Kind.of.Hash(a: 1) # {a: 1}
93
100
 
94
101
  # ---
95
102
 
@@ -99,14 +106,12 @@ Kind.of.Boolean(false) # false
99
106
  ```
100
107
 
101
108
  > **Note:** `Kind.of.<Type>` supports the to_proc protocol.
102
- > But it won't perform a strict validation, instead, it will return true
103
- > when the value has the desired kind and false if it hasn't.
109
+ > And it will perform a strict validation as expected.
104
110
 
105
111
  ```ruby
106
112
  collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
107
113
 
108
- collection
109
- .select(&Kind.of.Hash) # [{number: 1}, {number: 3}]
114
+ collection.map(&Kind.of.Hash) # Kind::Error ("number 2" expected to be a kind of Hash)
110
115
  ```
111
116
 
112
117
  When the verified value is nil, it is possible to define a default value with the same type to be returned.
@@ -123,6 +128,24 @@ Kind.of.Boolean(nil, or: true) # true
123
128
 
124
129
  > **Note:** As an alternative syntax, you can use the `Kind::Of` instead of the `Kind.of` method. e.g: `Kind::Of::Hash('')`
125
130
 
131
+ #### Method aliases to perform a strict validation
132
+
133
+ ```ruby
134
+ Kind.of.Hash[nil] # raise Kind::Error, "nil expected to be a kind of Hash"
135
+ Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
136
+ Kind.of.Hash[a: 1] # {a: 1}
137
+ Kind.of.Hash['', or: {}] # {}
138
+
139
+ # or
140
+
141
+ Kind.of.Hash.instance(nil) # raise Kind::Error, "nil expected to be a kind of Hash"
142
+ Kind.of.Hash.instance('') # raise Kind::Error, "'' expected to be a kind of Hash"
143
+ Kind.of.Hash.instance(a: 1) # {a: 1}
144
+ Kind.of.Hash.instance('', or: {}) # {}
145
+ ```
146
+
147
+ ### Kind.of.\<Type\>.or_nil()
148
+
126
149
  But if you don't need a strict type verification, use the `.or_nil` method.
127
150
 
128
151
  ```ruby
@@ -135,11 +158,12 @@ Kind.of.Boolean.or_nil('') # nil
135
158
  Kind.of.Boolean.or_nil(true) # true
136
159
  ```
137
160
 
138
- And just for convenience, you can use the method `.instance?` to verify if the given object has the expected type.
161
+ ### Kind.of.\<Type\>.instance?()
162
+
163
+ Use the method `.instance?` to verify if the given object has the expected type.
139
164
 
140
165
  ```ruby
141
- Kind.of.Hash.instance?('')
142
- # false
166
+ Kind.of.Hash.instance?('') # false
143
167
 
144
168
  # ---
145
169
 
@@ -155,27 +179,19 @@ Kind.of.Boolean.instance?(false) # true
155
179
  collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
156
180
 
157
181
  collection
158
- .select(&Kind.of.Hash.instance?)
159
- .reduce(0) { |total, item| total + item.fetch(:number, 0) } # 4
182
+ .select(&Kind.of.Hash.instance?) # [{:number=>1}, {:number=>3}]
160
183
  ```
161
184
 
162
- Also, there are aliases to perform the strict type verification. e.g:
185
+ > **Note:** You can use a different syntax to perform an instance verification.
186
+ > To do this, use Kind.of.\<Type\>?()
163
187
 
164
188
  ```ruby
165
- Kind.of.Hash[nil] # raise Kind::Error, "nil expected to be a kind of Hash"
166
- Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
167
- Kind.of.Hash[a: 1] # {a: 1}
168
- Kind.of.Hash['', or: {}] # {}
169
-
170
- # or
189
+ collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
171
190
 
172
- Kind.of.Hash.instance(nil) # raise Kind::Error, "nil expected to be a kind of Hash"
173
- Kind.of.Hash.instance('') # raise Kind::Error, "'' expected to be a kind of Hash"
174
- Kind.of.Hash.instance(a: 1) # {a: 1}
175
- Kind.of.Hash.instance('', or: {}) # {}
191
+ collection.select(&Kind.of.Hash?) # [{:number=>1}, {:number=>3}]
176
192
  ```
177
193
 
178
- ### Verifying the kind of some class/module
194
+ ### Kind.is.\<Type\>() - Verifying if some class/module is the expected kind.
179
195
 
180
196
  You can use `Kind.is` to verify if some class has the expected type as its ancestor.
181
197
 
@@ -262,6 +278,22 @@ Kind.of(User, {}) # Kind::Error ({} expected to be a kind of User)
262
278
  Kind.of(Hash, {}) # {}
263
279
  Kind.of(Hash, user) # Kind::Error (<User ...> expected to be a kind of Hash)
264
280
 
281
+ # ----------------------------------------- #
282
+ # Verifiyng if the value is a kind instance #
283
+ # ----------------------------------------- #
284
+
285
+ Kind.of?(Numeric, 1) # true
286
+ Kind.of?(Numeric, 1, 2.0) # true
287
+
288
+ Kind.of?(Numeric, '1') # false
289
+ Kind.of?(Numeric, 1, '2.0') # false
290
+
291
+ # Note: Kind.of?(Type) without arguments will return a
292
+ # lambda that will perform an instance verification
293
+ #
294
+ [1, '2', 3.0, '4']
295
+ .select(&Kind.of?(Numeric)) # [1, 3.0]
296
+
265
297
  # ---------------------------------- #
266
298
  # Creating type checkers dynamically #
267
299
  # ---------------------------------- #
@@ -300,7 +332,7 @@ end
300
332
  Kind.is(User, AdminUser) # true
301
333
  ```
302
334
 
303
- #### Registering new (custom) type checkers
335
+ #### Registering new (custom) type checker
304
336
 
305
337
  Use `Kind::Types.add()`. e.g:
306
338
 
@@ -491,7 +523,27 @@ puts optional.value_or(1) # 1
491
523
  puts optional.value_or { 1 } # 1
492
524
  ```
493
525
 
494
- ### Kind::Maybe[] and Kind::Maybe#then
526
+ #### Replacing blocks by lambdas
527
+
528
+ ```ruby
529
+ Add = -> params do
530
+ a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
531
+
532
+ a + b if Kind.of.Numeric?(a, b)
533
+ end
534
+
535
+ # --
536
+
537
+ Kind::Maybe.new(a: 1, b: 2).map(&Add).value_or(0) # 3
538
+
539
+ # --
540
+
541
+ Kind::Maybe.new([]).map(&Add).value_or(0) # 0
542
+ Kind::Maybe.new({}).map(&Add).value_or(0) # 0
543
+ Kind::Maybe.new(nil).map(&Add).value_or(0) # 0
544
+ ```
545
+
546
+ ### Kind::Maybe[] and Kind::Maybe#then method aliases
495
547
 
496
548
  You can use `Kind::Maybe[]` (brackets) instead of the `.new` to transform values in a `Kind::Maybe`. Another alias is `.then` to the `.map` method.
497
549
 
@@ -505,43 +557,57 @@ result =
505
557
  puts result # 42
506
558
  ```
507
559
 
508
- ### Kind::Maybe#try
509
-
510
- If you don't want to use a map to access the value, you could use the `#try` method to access it. So, if the value wasn't `nil` or `Kind::Undefined`, it will be returned.
560
+ #### Replacing blocks by lambdas
511
561
 
512
562
  ```ruby
513
- object = 'foo'
563
+ Add = -> params do
564
+ a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
514
565
 
515
- p Kind::Maybe[object].try(:upcase) # "FOO"
566
+ a + b if Kind.of.Numeric.instance?(a, b)
567
+ end
516
568
 
517
- p Kind::Maybe[{}].try(:fetch, :number, 0) # 0
569
+ # --
518
570
 
519
- p Kind::Maybe[{number: 1}].try(:fetch, :number) # 1
571
+ Kind::Maybe[a: 1, b: 2].then(&Add).value_or(0) # 3
520
572
 
521
- p Kind::Maybe[object].try { |value| value.upcase } # "FOO"
573
+ # --
522
574
 
523
- #############
524
- # Nil value #
525
- #############
575
+ Kind::Maybe[1].then(&Add).value_or(0) # 0
576
+ Kind::Maybe['2'].then(&Add).value_or(0) # 0
577
+ Kind::Maybe[nil].then(&Add).value_or(0) # 0
578
+ ```
526
579
 
527
- object = nil
580
+ ### Kind::None() and Kind::Some()
528
581
 
529
- p Kind::Maybe[object].try(:upcase) # nil
582
+ If you need to ensure the return of `Kind::Maybe` results from your methods/lambdas,
583
+ you could use the methods `Kind::None` and `Kind::Some` to do this. e.g:
530
584
 
531
- p Kind::Maybe[object].try { |value| value.upcase } # nil
585
+ ```ruby
586
+ Add = -> params do
587
+ a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
532
588
 
533
- #########################
534
- # Kind::Undefined value #
535
- #########################
589
+ return Kind::None unless Kind.of.Numeric.instance?(a, b)
536
590
 
537
- object = Kind::Undefined
591
+ Kind::Some(a + b)
592
+ end
538
593
 
539
- p Kind::Maybe[object].try(:upcase) # nil
594
+ # --
540
595
 
541
- p Kind::Maybe[object].try { |value| value.upcase } # nil
542
- ```
596
+ Add.call(1) # #<Kind::Maybe::None:0x0000... @value=nil>
597
+ Add.call({}) # #<Kind::Maybe::None:0x0000... @value=nil>
598
+ Add.call(a: 1) # #<Kind::Maybe::None:0x0000... @value=nil>
599
+ Add.call(b: 2) # #<Kind::Maybe::None:0x0000... @value=nil>
543
600
 
544
- [⬆️ Back to Top](#table-of-contents-)
601
+ Add.call(a:1, b: 2) # #<Kind::Maybe::Some:0x0000... @value=3>
602
+
603
+ # --
604
+
605
+ Kind::Maybe[a: 1, b: 2].then(&Add).value_or(0) # 3
606
+
607
+ Kind::Maybe[1].then(&Add).value_or(0) # 0
608
+ Kind::Maybe['2'].then(&Add).value_or(0) # 0
609
+ Kind::Maybe[nil].then(&Add).value_or(0) # 0
610
+ ```
545
611
 
546
612
  ### Kind.of.Maybe()
547
613
 
@@ -598,6 +664,26 @@ result2 =
598
664
  puts result2 # 35
599
665
  ```
600
666
 
667
+ #### Replacing blocks by lambdas
668
+
669
+ ```ruby
670
+ Add = -> params do
671
+ a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
672
+
673
+ a + b if Kind.of.Numeric.instance?(a, b)
674
+ end
675
+
676
+ # --
677
+
678
+ Kind::Optional[a: 1, b: 2].then(&Add).value_or(0) # 3
679
+
680
+ # --
681
+
682
+ Kind::Optional[1].then(&Add).value_or(0) # 0
683
+ Kind::Optional['2'].then(&Add).value_or(0) # 0
684
+ Kind::Optional[nil].then(&Add).value_or(0) # 0
685
+ ```
686
+
601
687
  **Note:** The `Kind.of.Optional` is available to check if some value is a `Kind::Optional`.
602
688
 
603
689
  [⬆️ Back to Top](#table-of-contents-)
@@ -709,6 +795,44 @@ end
709
795
 
710
796
  [⬆️ Back to Top](#table-of-contents-)
711
797
 
798
+ ### Kind::Maybe#try
799
+
800
+ If you don't want to use a map to access the value, you could use the `#try` method to access it. So, if the value wasn't `nil` or `Kind::Undefined`, it will be returned.
801
+
802
+ ```ruby
803
+ object = 'foo'
804
+
805
+ p Kind::Maybe[object].try(:upcase) # "FOO"
806
+
807
+ p Kind::Maybe[{}].try(:fetch, :number, 0) # 0
808
+
809
+ p Kind::Maybe[{number: 1}].try(:fetch, :number) # 1
810
+
811
+ p Kind::Maybe[object].try { |value| value.upcase } # "FOO"
812
+
813
+ #############
814
+ # Nil value #
815
+ #############
816
+
817
+ object = nil
818
+
819
+ p Kind::Maybe[object].try(:upcase) # nil
820
+
821
+ p Kind::Maybe[object].try { |value| value.upcase } # nil
822
+
823
+ #########################
824
+ # Kind::Undefined value #
825
+ #########################
826
+
827
+ object = Kind::Undefined
828
+
829
+ p Kind::Maybe[object].try(:upcase) # nil
830
+
831
+ p Kind::Maybe[object].try { |value| value.upcase } # nil
832
+ ```
833
+
834
+ [⬆️ Back to Top](#table-of-contents-)
835
+
712
836
  ## Kind::Validator (ActiveModel::Validations)
713
837
 
714
838
  This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, < 6.1.0`](https://api.rubyonrails.org/classes/ActiveModel/Validations.html). e.g
@@ -839,7 +963,6 @@ Kind::Validator.default_strategy = :instance_of
839
963
  ```
840
964
 
841
965
  And these are the available options to define the default strategy:
842
- - `is_a`
843
966
  - `kind_of` *(default)*
844
967
  - `instance_of`
845
968
 
data/lib/kind.rb CHANGED
@@ -29,6 +29,12 @@ module Kind
29
29
 
30
30
  private_constant :MODULE_OR_CLASS
31
31
 
32
+ private_class_method def self.__checkers__
33
+ @__checkers__ ||= {}
34
+ end
35
+
36
+ __checkers__
37
+
32
38
  def self.of(kind = Undefined, object = Undefined)
33
39
  return Of if kind == Undefined && object == Undefined
34
40
 
@@ -45,8 +51,8 @@ module Kind
45
51
  end
46
52
  end
47
53
 
48
- private_class_method def self.__checkers__
49
- @__checkers__ ||= {}
54
+ def self.of?(kind, *args)
55
+ Kind.of(kind).instance?(*args)
50
56
  end
51
57
 
52
58
  # --------------------- #
@@ -90,6 +96,10 @@ module Kind
90
96
  def self.__is_instance__(value); class?(value); end
91
97
  end)
92
98
 
99
+ def self.Class?(*args)
100
+ Kind::Of::Class.instance?(*args)
101
+ end
102
+
93
103
  # -- Module
94
104
 
95
105
  def self.Module(object = Undefined)
@@ -136,6 +146,10 @@ module Kind
136
146
  def self.__is_instance__(value); class?(value); end
137
147
  end)
138
148
 
149
+ def self.Module?(*args)
150
+ Kind::Of::Module.instance?(*args)
151
+ end
152
+
139
153
  # -- Boolean
140
154
 
141
155
  def self.Boolean(object = Undefined, options = Empty::HASH)
@@ -187,6 +201,10 @@ module Kind
187
201
  end
188
202
  end)
189
203
 
204
+ def self.Boolean?(*args)
205
+ Kind::Of::Boolean.instance?(*args)
206
+ end
207
+
190
208
  # -- Lambda
191
209
 
192
210
  def self.Lambda(object = Undefined, options = Empty::HASH)
@@ -231,6 +249,10 @@ module Kind
231
249
  end
232
250
  end)
233
251
 
252
+ def self.Lambda?(*args)
253
+ Kind::Of::Lambda.instance?(*args)
254
+ end
255
+
234
256
  # -- Callable
235
257
 
236
258
  def self.Callable(object = Undefined, options = Empty::HASH)
@@ -279,6 +301,10 @@ module Kind
279
301
  end
280
302
  end)
281
303
 
304
+ def self.Callable?(*args)
305
+ Kind::Of::Callable.instance?(*args)
306
+ end
307
+
282
308
  # ---------------------- #
283
309
  # Built-in type checkers #
284
310
  # ---------------------- #
data/lib/kind/checker.rb CHANGED
@@ -18,21 +18,29 @@ module Kind
18
18
  instance(value, options)
19
19
  end
20
20
 
21
- def instance?(value = Kind::Undefined)
22
- return __is_instance__(value) if value != Kind::Undefined
23
-
24
- to_proc
21
+ def to_proc
22
+ @to_proc ||=
23
+ -> checker { -> value { checker.instance(value) } }.call(self)
25
24
  end
26
25
 
27
26
  def __is_instance__(value)
28
- value.is_a?(__kind)
27
+ value.kind_of?(__kind)
29
28
  end
30
29
 
31
- def to_proc
32
- @to_proc ||=
30
+ def is_instance_to_proc
31
+ @is_instance_to_proc ||=
33
32
  -> checker { -> value { checker.__is_instance__(value) } }.call(self)
34
33
  end
35
34
 
35
+ def instance?(*args)
36
+ return is_instance_to_proc if args.empty?
37
+
38
+ return args.all? { |object| __is_instance__(object) } if args.size > 1
39
+
40
+ arg = args[0]
41
+ arg == Kind::Undefined ? is_instance_to_proc : __is_instance__(arg)
42
+ end
43
+
36
44
  def or_nil(value)
37
45
  return value if instance?(value)
38
46
  end
@@ -41,6 +49,15 @@ module Kind
41
49
  or_nil(value) || Kind::Undefined
42
50
  end
43
51
 
52
+ def __as_maybe__(value)
53
+ Kind::Maybe.new(or_nil(value))
54
+ end
55
+
56
+ def as_maybe_to_proc
57
+ @as_maybe_to_proc ||=
58
+ -> checker { -> value { checker.__as_maybe__(value) } }.call(self)
59
+ end
60
+
44
61
  def as_maybe(value = Kind::Undefined)
45
62
  return __as_maybe__(value) if value != Kind::Undefined
46
63
 
@@ -50,15 +67,6 @@ module Kind
50
67
  def as_optional(value = Kind::Undefined)
51
68
  as_maybe(value)
52
69
  end
53
-
54
- def __as_maybe__(value)
55
- Kind::Maybe.new(or_nil(value))
56
- end
57
-
58
- def as_maybe_to_proc
59
- @as_maybe_to_proc ||=
60
- -> checker { -> value { checker.__as_maybe__(value) } }.call(self)
61
- end
62
70
  end
63
71
 
64
72
  private_constant :Checkable
data/lib/kind/maybe.rb CHANGED
@@ -16,7 +16,7 @@ module Kind
16
16
  attr_reader :value
17
17
 
18
18
  def initialize(value)
19
- @value = value
19
+ @value = value.kind_of?(Result) ? value.value : value
20
20
  end
21
21
 
22
22
  def value_or(method_name = Undefined, &block)
@@ -44,7 +44,7 @@ module Kind
44
44
  def value_or(default = Undefined, &block)
45
45
  raise ArgumentError, INVALID_DEFAULT_ARG if default == Undefined && !block
46
46
 
47
- Maybe::Value.some?(default) ? default : block.call
47
+ default != Undefined ? default : block.call
48
48
  end
49
49
 
50
50
  def none?; true; end
@@ -79,6 +79,7 @@ module Kind
79
79
  def map(&fn)
80
80
  result = fn.call(@value)
81
81
 
82
+ return result if Maybe::None === result
82
83
  return NONE_WITH_NIL_VALUE if result == nil
83
84
  return NONE_WITH_UNDEFINED_VALUE if result == Undefined
84
85
 
@@ -98,13 +99,37 @@ module Kind
98
99
 
99
100
  def self.new(value)
100
101
  result_type = Maybe::Value.none?(value) ? None : Some
101
- result_type.new(value.is_a?(Result) ? value.value : value)
102
+ result_type.new(value)
102
103
  end
103
104
 
104
105
  def self.[](value);
105
106
  new(value)
106
107
  end
108
+
109
+ def self.none
110
+ NONE_WITH_NIL_VALUE
111
+ end
112
+
113
+ VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
114
+
115
+ private_constant :VALUE_CANT_BE_NONE
116
+
117
+ def self.some(value)
118
+ return Maybe::Some.new(value) if Value.some?(value)
119
+
120
+ raise ArgumentError, VALUE_CANT_BE_NONE
121
+ end
107
122
  end
108
123
 
109
124
  Optional = Maybe
125
+
126
+ None = Maybe.none
127
+
128
+ def self.None
129
+ Kind::None
130
+ end
131
+
132
+ def self.Some(value)
133
+ Maybe.some(value)
134
+ end
110
135
  end
data/lib/kind/types.rb CHANGED
@@ -12,7 +12,17 @@ module Kind
12
12
 
13
13
  return Kind::Of::%{kind_name} if object == Undefined && default.nil?
14
14
 
15
- Kind::Of.(::%{kind_name_to_check}, (object || default))
15
+ is_instance = Kind::Of::%{kind_name}.__is_instance__(object)
16
+
17
+ return object if is_instance
18
+
19
+ Kind::Of.(::%{kind_name_to_check}, object && default ? default : object || default)
20
+ end
21
+ RUBY
22
+
23
+ KIND_OF_IS = <<-RUBY
24
+ def self.%{method_name}?(*args)
25
+ Kind::Of::%{kind_name}.instance?(*args)
16
26
  end
17
27
  RUBY
18
28
 
@@ -93,6 +103,7 @@ module Kind
93
103
 
94
104
  kind_of_mod.instance_eval(KIND_OF % params)
95
105
  kind_of_mod.const_set(method_name, kind_checker)
106
+ kind_of_mod.instance_eval(KIND_OF_IS % params)
96
107
  end
97
108
 
98
109
  unless kind_is_mod.respond_to?(method_name)
data/lib/kind/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kind
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-07 00:00:00.000000000 Z
11
+ date: 2020-05-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple type system (at runtime) for Ruby - free of dependencies.
14
14
  email: