kind 4.1.0 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -1
  3. data/.travis.sh +39 -7
  4. data/.travis.yml +1 -2
  5. data/CHANGELOG.md +524 -29
  6. data/Gemfile +13 -6
  7. data/README.md +57 -43
  8. data/kind.gemspec +3 -3
  9. data/lib/kind.rb +2 -84
  10. data/lib/kind/__lib__/action_steps.rb +57 -0
  11. data/lib/kind/__lib__/attributes.rb +66 -0
  12. data/lib/kind/__lib__/kind.rb +51 -0
  13. data/lib/kind/__lib__/of.rb +17 -0
  14. data/lib/kind/__lib__/strict.rb +49 -0
  15. data/lib/kind/__lib__/undefined.rb +14 -0
  16. data/lib/kind/action.rb +127 -0
  17. data/lib/kind/active_model/validation.rb +3 -4
  18. data/lib/kind/basic.rb +79 -0
  19. data/lib/kind/basic/error.rb +29 -0
  20. data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
  21. data/lib/kind/dig.rb +21 -5
  22. data/lib/kind/either.rb +30 -0
  23. data/lib/kind/either/left.rb +29 -0
  24. data/lib/kind/either/methods.rb +17 -0
  25. data/lib/kind/either/monad.rb +65 -0
  26. data/lib/kind/either/monad/wrapper.rb +19 -0
  27. data/lib/kind/either/right.rb +38 -0
  28. data/lib/kind/empty.rb +2 -2
  29. data/lib/kind/empty/constant.rb +7 -0
  30. data/lib/kind/enum.rb +63 -0
  31. data/lib/kind/enum/item.rb +40 -0
  32. data/lib/kind/enum/methods.rb +72 -0
  33. data/lib/kind/function.rb +45 -0
  34. data/lib/kind/functional.rb +89 -0
  35. data/lib/kind/functional/action.rb +87 -0
  36. data/lib/kind/functional/steps.rb +22 -0
  37. data/lib/kind/immutable_attributes.rb +34 -0
  38. data/lib/kind/immutable_attributes/initializer.rb +70 -0
  39. data/lib/kind/immutable_attributes/reader.rb +38 -0
  40. data/lib/kind/maybe.rb +37 -12
  41. data/lib/kind/maybe/methods.rb +21 -0
  42. data/lib/kind/maybe/monad.rb +82 -0
  43. data/lib/kind/maybe/monad/wrapper.rb +19 -0
  44. data/lib/kind/maybe/none.rb +12 -19
  45. data/lib/kind/maybe/some.rb +68 -26
  46. data/lib/kind/maybe/typed.rb +11 -5
  47. data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +8 -4
  48. data/lib/kind/monad.rb +22 -0
  49. data/lib/kind/monads.rb +5 -0
  50. data/lib/kind/objects.rb +17 -0
  51. data/lib/kind/objects/basic_object.rb +43 -0
  52. data/lib/kind/objects/modules.rb +32 -0
  53. data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
  54. data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
  55. data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
  56. data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
  57. data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
  58. data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
  59. data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
  60. data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
  61. data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
  62. data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
  63. data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
  64. data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
  65. data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
  66. data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
  67. data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
  68. data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
  69. data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
  70. data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
  71. data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
  72. data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
  73. data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
  74. data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
  75. data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
  76. data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
  77. data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
  78. data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
  79. data/lib/kind/objects/nil.rb +17 -0
  80. data/lib/kind/objects/not_nil.rb +9 -0
  81. data/lib/kind/objects/object.rb +56 -0
  82. data/lib/kind/objects/respond_to.rb +30 -0
  83. data/lib/kind/objects/union_type.rb +44 -0
  84. data/lib/kind/presence.rb +4 -2
  85. data/lib/kind/result.rb +31 -0
  86. data/lib/kind/result/abstract.rb +53 -0
  87. data/lib/kind/result/failure.rb +33 -0
  88. data/lib/kind/result/methods.rb +17 -0
  89. data/lib/kind/result/monad.rb +74 -0
  90. data/lib/kind/result/monad/wrapper.rb +19 -0
  91. data/lib/kind/result/success.rb +53 -0
  92. data/lib/kind/strict/disabled.rb +34 -0
  93. data/lib/kind/try.rb +22 -10
  94. data/lib/kind/validator.rb +111 -0
  95. data/lib/kind/version.rb +1 -1
  96. metadata +84 -51
  97. data/lib/kind/active_model/kind_validator.rb +0 -103
  98. data/lib/kind/core.rb +0 -10
  99. data/lib/kind/core/deprecation.rb +0 -29
  100. data/lib/kind/core/kind.rb +0 -61
  101. data/lib/kind/core/undefined.rb +0 -7
  102. data/lib/kind/core/wrong_number_of_args.rb +0 -9
  103. data/lib/kind/deprecations/built_in_type_checkers.rb +0 -23
  104. data/lib/kind/deprecations/checker.rb +0 -16
  105. data/lib/kind/deprecations/checker/factory.rb +0 -31
  106. data/lib/kind/deprecations/checker/protocol.rb +0 -73
  107. data/lib/kind/deprecations/is.rb +0 -35
  108. data/lib/kind/deprecations/of.rb +0 -258
  109. data/lib/kind/deprecations/types.rb +0 -121
  110. data/lib/kind/error.rb +0 -15
  111. data/lib/kind/maybe/result.rb +0 -51
  112. data/lib/kind/type_checker.rb +0 -87
  113. data/lib/kind/type_checkers.rb +0 -30
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module KIND
5
- def self.null?(value) # :nodoc:
6
- value.nil? || Undefined == value
7
- end
8
-
9
- def self.of?(kind, values) # :nodoc:
10
- of_kind = -> value { kind === value }
11
-
12
- values.empty? ? of_kind : values.all?(&of_kind)
13
- end
14
-
15
- def self.of!(kind, value, kind_name = nil) # :nodoc:
16
- return value if kind === value
17
-
18
- error!(kind_name || kind.name, value)
19
- end
20
-
21
- def self.error!(kind_name, value) # :nodoc:
22
- raise Error.new(kind_name, value)
23
- end
24
-
25
- def self.of_class?(value) # :nodoc:
26
- value.kind_of?(::Class)
27
- end
28
-
29
- def self.of_module?(value) # :nodoc:
30
- ::Module == value || (value.kind_of?(::Module) && !of_class?(value))
31
- end
32
-
33
- def self.of_module_or_class!(value) # :nodoc:
34
- of!(::Module, value, 'Module/Class')
35
- end
36
-
37
- def self.respond_to!(method_name, value) # :nodoc:
38
- return value if value.respond_to?(method_name)
39
-
40
- raise Error.new("expected #{value} to respond to :#{method_name}")
41
- end
42
-
43
- def self.is?(expected, value) # :nodoc:
44
- is!(of_module_or_class!(expected), value)
45
- end
46
-
47
- def self.is!(expected_kind, value) # :nodoc:
48
- kind = of_module_or_class!(value)
49
-
50
- if of_class?(kind)
51
- kind <= expected_kind || expected_kind == ::Class
52
- else
53
- kind == expected_kind || kind.kind_of?(expected_kind)
54
- end
55
- end
56
-
57
- def self.value(kind, arg, default) # :nodoc:
58
- kind === arg ? arg : default
59
- end
60
- end
61
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- UNDEFINED = Object.new.freeze
5
-
6
- private_constant :UNDEFINED
7
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module WRONG_NUMBER_OF_ARGS
5
- def self.error!(given:, expected:)
6
- raise ArgumentError, "wrong number of arguments (given #{given}, expected #{expected})"
7
- end
8
- end
9
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- # -- Classes
5
- [
6
- ::String, ::Symbol, ::Numeric, ::Integer, ::Float, ::Regexp, ::Time,
7
- ::Array, ::Range, ::Hash, ::Struct, ::Enumerator, ::Set, ::OpenStruct,
8
- ::Method, ::Proc,
9
- ::IO, ::File
10
- ].each { |klass| Types.add(klass) }
11
-
12
- Types.add(::Queue, name: 'Queue'.freeze)
13
-
14
- # -- Modules
15
- [
16
- ::Enumerable, ::Comparable
17
- ].each { |klass| Types.add(klass) }
18
-
19
- # -- Kind::Of::Maybe
20
-
21
- Types.add(Kind::Maybe::Result, name: 'Maybe'.freeze)
22
- Types.add(Kind::Maybe::Result, name: 'Optional'.freeze)
23
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kind/deprecations/checker/factory'
4
- require 'kind/deprecations/checker/protocol'
5
-
6
- module Kind
7
- class Checker
8
- include Protocol
9
-
10
- attr_reader :__kind
11
-
12
- def initialize(kind)
13
- @__kind = kind
14
- end
15
- end
16
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
-
5
- module Kind
6
- class Checker
7
- class Factory
8
- include Singleton
9
-
10
- def self.create(kind)
11
- instance.create(kind)
12
- end
13
-
14
- def initialize
15
- @__checkers__ = {}
16
- end
17
-
18
- def create(kind)
19
- @__checkers__[kind] ||= begin
20
- kind_name = kind.name
21
-
22
- if Kind::Of.const_defined?(kind_name, false)
23
- Kind::Of.const_get(kind_name)
24
- else
25
- Kind::Checker.new(Kind.of_module_or_class(kind))
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- class Checker
5
- module Protocol
6
- def class?(value)
7
- KIND.is?(__kind, value)
8
- end
9
-
10
- def instance(value, options = Empty::HASH)
11
- default = options[:or]
12
-
13
- return KIND.of!(__kind, value) if ::Kind::KIND.null?(default)
14
-
15
- Kind::Undefined != value && instance?(value) ? value : KIND.of!(__kind, default)
16
- end
17
-
18
- def [](value, options = options = Empty::HASH)
19
- instance(value, options)
20
- end
21
-
22
- def to_proc
23
- @to_proc ||=
24
- -> checker { -> value { checker.instance(value) } }.call(self)
25
- end
26
-
27
- def __is_instance__(value)
28
- value.kind_of?(__kind)
29
- end
30
-
31
- def is_instance_to_proc
32
- @is_instance_to_proc ||=
33
- -> checker { -> value { checker.__is_instance__(value) } }.call(self)
34
- end
35
-
36
- def instance?(*args)
37
- return is_instance_to_proc if args.empty?
38
-
39
- return args.all? { |object| __is_instance__(object) } if args.size > 1
40
-
41
- arg = args[0]
42
- Kind::Undefined == arg ? is_instance_to_proc : __is_instance__(arg)
43
- end
44
-
45
- def or_nil(value)
46
- return value if instance?(value)
47
- end
48
-
49
- def or_undefined(value)
50
- or_nil(value) || Kind::Undefined
51
- end
52
-
53
- def __as_maybe__(value)
54
- Kind::Maybe.new(or_nil(value))
55
- end
56
-
57
- def as_maybe_to_proc
58
- @as_maybe_to_proc ||=
59
- -> checker { -> value { checker.__as_maybe__(value) } }.call(self)
60
- end
61
-
62
- def as_maybe(value = Kind::Undefined)
63
- return __as_maybe__(value) if Kind::Undefined != value
64
-
65
- as_maybe_to_proc
66
- end
67
-
68
- def as_optional(value = Kind::Undefined)
69
- as_maybe(value)
70
- end
71
- end
72
- end
73
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Is
5
- def self.call(expected, object)
6
- DEPRECATION.warn_method_replacement('Kind::Is.call', 'Kind::KIND.is?')
7
-
8
- KIND.is?(expected, object)
9
- end
10
-
11
- def self.Class(value)
12
- DEPRECATION.warn_method_replacement('Kind::Is.Class', 'Kind.of_class?')
13
-
14
- Kind.of_class?(value)
15
- end
16
-
17
- def self.Module(value)
18
- DEPRECATION.warn_method_replacement('Kind::Is.Module', 'Kind.of_module?')
19
-
20
- Kind.of_module?(value)
21
- end
22
-
23
- def self.Boolean(value)
24
- DEPRECATION.warn_removal('Kind::Is.Boolean')
25
-
26
- Kind::Class[value] <= TrueClass || value <= FalseClass
27
- end
28
-
29
- def self.Callable(value)
30
- DEPRECATION.warn_method_replacement('Kind::Is.Callable', 'Kind::Callable?')
31
-
32
- value.respond_to?(:call)
33
- end
34
- end
35
- end
@@ -1,258 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Of
5
- def self.call(kind, object, kind_name = nil)
6
- DEPRECATION.warn_method_replacement('Kind::Of.call', 'Kind::KIND.of!')
7
-
8
- KIND.of!(kind, object, kind_name)
9
- end
10
-
11
- # -- Class
12
-
13
- def self.Class(object = Undefined)
14
- DEPRECATION.warn_method_replacement('Kind::Of::Class', 'Kind::Class')
15
-
16
- return Class if Undefined == object
17
-
18
- self.call(::Class, object)
19
- end
20
-
21
- const_set(:Class, ::Module.new do
22
- extend Checker::Protocol
23
-
24
- def self.__kind; ::Class; end
25
-
26
- def self.class?(value); Kind.of_class?(value); end
27
-
28
- def self.__is_instance__(value); class?(value); end
29
- end)
30
-
31
- def self.Class?(*args)
32
- DEPRECATION.warn_method_replacement('Kind::Of::Class?', 'Kind::Class?')
33
-
34
- Kind::Class?(*args)
35
- end
36
-
37
- # -- Module
38
-
39
- def self.Module(object = Undefined)
40
- DEPRECATION.warn_method_replacement('Kind::Of::Module', 'Kind::Module')
41
-
42
- return Module if Undefined == object
43
-
44
- self.call(::Module, object)
45
- end
46
-
47
- const_set(:Module, ::Module.new do
48
- extend Checker::Protocol
49
-
50
- def self.__kind_undefined(value)
51
- __kind_error(Kind::Undefined) if Kind::Undefined == value
52
-
53
- yield
54
- end
55
-
56
- def self.__kind_error(value)
57
- raise Kind::Error.new('Module'.freeze, value)
58
- end
59
-
60
- def self.__kind_of(value)
61
- return value if Kind.of_module?(value)
62
-
63
- __kind_error(value)
64
- end
65
-
66
- def self.__kind; ::Module; end
67
-
68
- def self.class?(value); Kind.of_module?(value); end
69
-
70
- def self.instance(value, options = Empty::HASH)
71
- default = options[:or]
72
-
73
- if ::Kind::KIND.null?(default)
74
- __kind_undefined(value) { __kind_of(value) }
75
- else
76
- return value if Kind::Undefined != value && instance?(value)
77
-
78
- __kind_undefined(default) { __kind_of(default) }
79
- end
80
- end
81
-
82
- def self.__is_instance__(value); class?(value); end
83
- end)
84
-
85
- def self.Module?(*args)
86
- DEPRECATION.warn_method_replacement('Kind::Of::Module?', 'Kind::Module?')
87
-
88
- Kind::Module?(*args)
89
- end
90
-
91
- # -- Boolean
92
-
93
- def self.Boolean(object = Undefined, options = Empty::HASH)
94
- DEPRECATION.warn_method_replacement('Kind::Of::Boolean', 'Kind::Boolean')
95
-
96
- default = options[:or]
97
-
98
- return Kind::Of::Boolean if Undefined == object && default.nil?
99
-
100
- bool = object.nil? ? default : object
101
-
102
- return bool if bool.is_a?(::TrueClass) || bool.is_a?(::FalseClass)
103
-
104
- raise Kind::Error.new('Boolean'.freeze, bool)
105
- end
106
-
107
- const_set(:Boolean, ::Module.new do
108
- extend Checker::Protocol
109
-
110
- def self.__kind; [TrueClass, FalseClass].freeze; end
111
-
112
- def self.class?(value); Kind.is.Boolean(value); end
113
-
114
- def self.instance(value, options= Empty::HASH)
115
- default = options[:or]
116
-
117
- if ::Kind::KIND.null?(default)
118
- __kind_undefined(value) { Kind::Of::Boolean(value) }
119
- else
120
- return value if Kind::Undefined != value && instance?(value)
121
-
122
- __kind_undefined(default) { Kind::Of::Boolean(default) }
123
- end
124
- end
125
-
126
- def self.__kind_undefined(value)
127
- if Kind::Undefined == value
128
- raise Kind::Error.new('Boolean'.freeze, Kind::Undefined)
129
- else
130
- yield
131
- end
132
- end
133
-
134
- def self.__is_instance__(value);
135
- value.is_a?(TrueClass) || value.is_a?(FalseClass)
136
- end
137
-
138
- def self.or_undefined(value)
139
- result = or_nil(value)
140
- result.nil? ? Kind::Undefined : result
141
- end
142
- end)
143
-
144
- def self.Boolean?(*args)
145
- DEPRECATION.warn_method_replacement('Kind::Of::Boolean?', 'Kind::Boolean?')
146
-
147
- Kind::Boolean?(*args)
148
- end
149
-
150
- # -- Lambda
151
-
152
- def self.Lambda(object = Undefined, options = Empty::HASH)
153
- DEPRECATION.warn_method_replacement('Kind::Of::Lambda', 'Kind::Lambda')
154
-
155
- default = options[:or]
156
-
157
- return Kind::Of::Lambda if Undefined == object && default.nil?
158
-
159
- func = object || default
160
-
161
- return func if func.is_a?(::Proc) && func.lambda?
162
-
163
- raise Kind::Error.new('Lambda'.freeze, func)
164
- end
165
-
166
- const_set(:Lambda, ::Module.new do
167
- extend Checker::Protocol
168
-
169
- def self.__kind; ::Proc; end
170
-
171
- def self.instance(value, options = Empty::HASH)
172
- default = options[:or]
173
-
174
- if ::Kind::KIND.null?(default)
175
- __kind_undefined(value) { Kind::Of::Lambda(value) }
176
- else
177
- return value if Kind::Undefined != value && instance?(value)
178
-
179
- __kind_undefined(default) { Kind::Of::Lambda(default) }
180
- end
181
- end
182
-
183
- def self.__kind_undefined(value)
184
- if Kind::Undefined == value
185
- raise Kind::Error.new('Lambda'.freeze, Kind::Undefined)
186
- else
187
- yield
188
- end
189
- end
190
-
191
- def self.__is_instance__(value)
192
- value.is_a?(__kind) && value.lambda?
193
- end
194
- end)
195
-
196
- def self.Lambda?(*args)
197
- DEPRECATION.warn_method_replacement('Kind::Of::Lambda?', 'Kind::Lambda?')
198
-
199
- Kind::Lambda?(*args)
200
- end
201
-
202
- # -- Callable
203
-
204
- def self.Callable(object = Undefined, options = Empty::HASH)
205
- DEPRECATION.warn_method_replacement('Kind::Of::Callable', 'Kind::Callable')
206
-
207
- default = options[:or]
208
-
209
- return Kind::Of::Callable if Undefined == object && default.nil?
210
-
211
- callable = object || default
212
-
213
- return callable if callable.respond_to?(:call)
214
-
215
- raise Kind::Error.new('Callable'.freeze, callable)
216
- end
217
-
218
- const_set(:Callable, ::Module.new do
219
- extend Checker::Protocol
220
-
221
- def self.__kind; Object; end
222
-
223
- def self.class?(value)
224
- Kind::Is::Callable(value)
225
- end
226
-
227
- def self.instance(value, options = Empty::HASH)
228
- default = options[:or]
229
-
230
- if ::Kind::KIND.null?(default)
231
- __kind_undefined(value) { Kind::Of::Callable(value) }
232
- else
233
- return value if Kind::Undefined != value && instance?(value)
234
-
235
- __kind_undefined(default) { Kind::Of::Callable(default) }
236
- end
237
- end
238
-
239
- def self.__kind_undefined(value)
240
- if Kind::Undefined == value
241
- raise Kind::Error.new('Callable'.freeze, Kind::Undefined)
242
- else
243
- yield
244
- end
245
- end
246
-
247
- def self.__is_instance__(value);
248
- value.respond_to?(:call)
249
- end
250
- end)
251
-
252
- def self.Callable?(*args)
253
- DEPRECATION.warn_method_replacement('Kind::Of::Callable?', 'Kind::Callable?')
254
-
255
- Kind::Callable?(*args)
256
- end
257
- end
258
- end