kind 3.0.1 → 5.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -0
  3. data/.travis.sh +42 -12
  4. data/.travis.yml +7 -5
  5. data/CHANGELOG.md +1309 -0
  6. data/Gemfile +22 -7
  7. data/README.md +990 -490
  8. data/kind.gemspec +1 -1
  9. data/lib/kind.rb +29 -292
  10. data/lib/kind/active_model/validation.rb +3 -4
  11. data/lib/kind/core.rb +15 -0
  12. data/lib/kind/core/dig.rb +40 -0
  13. data/lib/kind/core/empty.rb +13 -0
  14. data/lib/kind/core/empty/constant.rb +7 -0
  15. data/lib/kind/{error.rb → core/error.rb} +2 -6
  16. data/lib/kind/core/maybe.rb +42 -0
  17. data/lib/kind/core/maybe/none.rb +57 -0
  18. data/lib/kind/core/maybe/result.rb +51 -0
  19. data/lib/kind/core/maybe/some.rb +90 -0
  20. data/lib/kind/core/maybe/typed.rb +29 -0
  21. data/lib/kind/core/maybe/wrappable.rb +33 -0
  22. data/lib/kind/core/presence.rb +33 -0
  23. data/lib/kind/core/try.rb +34 -0
  24. data/lib/kind/core/type_checker.rb +87 -0
  25. data/lib/kind/core/type_checkers.rb +30 -0
  26. data/lib/kind/core/type_checkers/custom/boolean.rb +19 -0
  27. data/lib/kind/core/type_checkers/custom/callable.rb +19 -0
  28. data/lib/kind/core/type_checkers/custom/lambda.rb +19 -0
  29. data/lib/kind/core/type_checkers/ruby/array.rb +17 -0
  30. data/lib/kind/core/type_checkers/ruby/class.rb +13 -0
  31. data/lib/kind/core/type_checkers/ruby/comparable.rb +13 -0
  32. data/lib/kind/core/type_checkers/ruby/enumerable.rb +13 -0
  33. data/lib/kind/core/type_checkers/ruby/enumerator.rb +13 -0
  34. data/lib/kind/core/type_checkers/ruby/file.rb +13 -0
  35. data/lib/kind/core/type_checkers/ruby/float.rb +13 -0
  36. data/lib/kind/core/type_checkers/ruby/hash.rb +17 -0
  37. data/lib/kind/core/type_checkers/ruby/integer.rb +13 -0
  38. data/lib/kind/core/type_checkers/ruby/io.rb +13 -0
  39. data/lib/kind/core/type_checkers/ruby/method.rb +13 -0
  40. data/lib/kind/core/type_checkers/ruby/module.rb +17 -0
  41. data/lib/kind/core/type_checkers/ruby/numeric.rb +13 -0
  42. data/lib/kind/core/type_checkers/ruby/proc.rb +13 -0
  43. data/lib/kind/core/type_checkers/ruby/queue.rb +14 -0
  44. data/lib/kind/core/type_checkers/ruby/range.rb +13 -0
  45. data/lib/kind/core/type_checkers/ruby/regexp.rb +13 -0
  46. data/lib/kind/core/type_checkers/ruby/string.rb +17 -0
  47. data/lib/kind/core/type_checkers/ruby/struct.rb +13 -0
  48. data/lib/kind/core/type_checkers/ruby/symbol.rb +13 -0
  49. data/lib/kind/core/type_checkers/ruby/time.rb +13 -0
  50. data/lib/kind/core/type_checkers/stdlib/open_struct.rb +13 -0
  51. data/lib/kind/core/type_checkers/stdlib/set.rb +17 -0
  52. data/lib/kind/{undefined.rb → core/undefined.rb} +4 -2
  53. data/lib/kind/core/utils/kind.rb +61 -0
  54. data/lib/kind/core/utils/undefined.rb +7 -0
  55. data/lib/kind/validator.rb +108 -1
  56. data/lib/kind/version.rb +1 -1
  57. data/test.sh +4 -4
  58. metadata +50 -15
  59. data/lib/kind/active_model/kind_validator.rb +0 -96
  60. data/lib/kind/checker.rb +0 -15
  61. data/lib/kind/checker/factory.rb +0 -35
  62. data/lib/kind/checker/protocol.rb +0 -73
  63. data/lib/kind/empty.rb +0 -21
  64. data/lib/kind/is.rb +0 -19
  65. data/lib/kind/maybe.rb +0 -183
  66. data/lib/kind/of.rb +0 -11
  67. data/lib/kind/types.rb +0 -115
@@ -1,35 +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
- MODULE_OR_CLASS = 'Module/Class'.freeze
19
-
20
- private_constant :MODULE_OR_CLASS
21
-
22
- def create(kind)
23
- @__checkers__[kind] ||= begin
24
- kind_name = kind.name
25
-
26
- if Kind::Of.const_defined?(kind_name, false)
27
- Kind::Of.const_get(kind_name)
28
- else
29
- Kind::Checker.new(Kind::Of.(Module, kind, MODULE_OR_CLASS))
30
- end
31
- end
32
- end
33
- end
34
- end
35
- 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.__call__(__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::Maybe::Value.none?(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
data/lib/kind/empty.rb DELETED
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
-
5
- module Kind
6
- module Empty
7
- SET = ::Set.new.freeze
8
-
9
- HASH = {}.freeze
10
-
11
- ARY = [].freeze
12
- ARRAY = ARY
13
-
14
- STR = ''.freeze
15
- STRING = STR
16
- end
17
- end
18
-
19
- unless defined?(Empty)
20
- Empty = Kind::Empty
21
- end
data/lib/kind/is.rb DELETED
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Is
5
- def self.call(expected, object)
6
- __call__(Kind::Of.Module(expected), object)
7
- end
8
-
9
- def self.__call__(expected_kind, object)
10
- kind = Kind::Of.Module(object)
11
-
12
- if kind.is_a?(Class)
13
- kind <= expected_kind || false
14
- else
15
- kind == expected_kind || kind.is_a?(expected_kind)
16
- end
17
- end
18
- end
19
- end
data/lib/kind/maybe.rb DELETED
@@ -1,183 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Maybe
5
- class Typed
6
- def initialize(kind)
7
- @kind_checker = Kind::Checker::Factory.create(kind)
8
- end
9
-
10
- def wrap(value)
11
- @kind_checker.as_maybe(value)
12
- end
13
-
14
- alias_method :new, :wrap
15
- alias_method :[], :wrap
16
- end
17
-
18
- module Value
19
- def self.none?(value)
20
- value.nil? || Undefined == value
21
- end
22
-
23
- def self.some?(value)
24
- !none?(value)
25
- end
26
- end
27
-
28
- class Result
29
- attr_reader :value
30
-
31
- def initialize(value)
32
- @value = value.kind_of?(Result) ? value.value : value
33
- end
34
-
35
- def value_or(method_name = Undefined, &block)
36
- raise NotImplementedError
37
- end
38
-
39
- def none?
40
- raise NotImplementedError
41
- end
42
-
43
- def some?; !none?; end
44
-
45
- def map(&fn)
46
- raise NotImplementedError
47
- end
48
-
49
- def try(method_name = Undefined, &block)
50
- raise NotImplementedError
51
- end
52
- end
53
-
54
- class None < Result
55
- INVALID_DEFAULT_ARG = 'the default value must be defined as an argument or block'.freeze
56
-
57
- def value_or(default = Undefined, &block)
58
- raise ArgumentError, INVALID_DEFAULT_ARG if Undefined == default && !block
59
-
60
- Undefined != default ? default : block.call
61
- end
62
-
63
- def none?; true; end
64
-
65
- def map(&fn)
66
- self
67
- end
68
-
69
- alias_method :then, :map
70
-
71
- def try!(method_name = Undefined, *args, &block)
72
- Kind.of.Symbol(method_name) if Undefined != method_name
73
-
74
- NONE_WITH_NIL_VALUE
75
- end
76
-
77
- alias_method :try, :try!
78
-
79
- private_constant :INVALID_DEFAULT_ARG
80
- end
81
-
82
- NONE_WITH_NIL_VALUE = None.new(nil)
83
- NONE_WITH_UNDEFINED_VALUE = None.new(Undefined)
84
-
85
- private_constant :NONE_WITH_NIL_VALUE, :NONE_WITH_UNDEFINED_VALUE
86
-
87
- class Some < Result
88
- def value_or(default = Undefined, &block)
89
- @value
90
- end
91
-
92
- def none?; false; end
93
-
94
- def map(&fn)
95
- result = fn.call(@value)
96
-
97
- resolve(result)
98
- end
99
-
100
- alias_method :then, :map
101
-
102
- def try!(method_name = Undefined, *args, &block)
103
- Kind::Of::Symbol(method_name) if Undefined != method_name
104
-
105
- __try__(method_name, args, block)
106
- end
107
-
108
- def try(method_name = Undefined, *args, &block)
109
- if (Undefined != method_name && value.respond_to?(Kind::Of::Symbol(method_name))) ||
110
- (Undefined == method_name && block)
111
- __try__(method_name, args, block)
112
- else
113
- NONE_WITH_NIL_VALUE
114
- end
115
- end
116
-
117
- private
118
-
119
- def __try__(method_name = Undefined, args, block)
120
- fn = Undefined == method_name ? block : method_name.to_proc
121
-
122
- result = args.empty? ? fn.call(value) : fn.call(*args.unshift(value))
123
-
124
- resolve(result)
125
- end
126
-
127
- def resolve(result)
128
- return result if Maybe::None === result
129
- return NONE_WITH_NIL_VALUE if result.nil?
130
- return NONE_WITH_UNDEFINED_VALUE if Undefined == result
131
-
132
- Some.new(result)
133
- end
134
- end
135
-
136
- def self.new(value)
137
- result_type = Maybe::Value.none?(value) ? None : Some
138
- result_type.new(value)
139
- end
140
-
141
- def self.[](value)
142
- new(value)
143
- end
144
-
145
- def self.wrap(value)
146
- new(value)
147
- end
148
-
149
- def self.none
150
- NONE_WITH_NIL_VALUE
151
- end
152
-
153
- VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
154
-
155
- private_constant :VALUE_CANT_BE_NONE
156
-
157
- def self.some(value)
158
- return Maybe::Some.new(value) if Value.some?(value)
159
-
160
- raise ArgumentError, VALUE_CANT_BE_NONE
161
- end
162
- end
163
-
164
- Optional = Maybe
165
-
166
- None = Maybe.none
167
-
168
- def self.None
169
- Kind::None
170
- end
171
-
172
- def self.Some(value)
173
- Maybe.some(value)
174
- end
175
-
176
- def self.Maybe(kind)
177
- Maybe::Typed.new(kind)
178
- end
179
-
180
- def self.Optional(kind)
181
- Maybe::Typed.new(kind)
182
- end
183
- end
data/lib/kind/of.rb DELETED
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Of
5
- def self.call(kind, object, kind_name = nil)
6
- return object if kind === object
7
-
8
- raise Kind::Error.new(kind_name || kind.name, object)
9
- end
10
- end
11
- end
data/lib/kind/types.rb DELETED
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kind
4
- module Types
5
- extend self
6
-
7
- COLONS = '::'.freeze
8
-
9
- KIND_OF = <<-RUBY
10
- def self.%{method_name}(object = Undefined, options = Empty::HASH)
11
- default = options[:or]
12
-
13
- return Kind::Of::%{kind_name} if Undefined == object && default.nil?
14
-
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)
26
- end
27
- RUBY
28
-
29
- KIND_IS = <<-RUBY
30
- def self.%{method_name}(value = Undefined)
31
- return Kind::Is::%{kind_name} if Undefined == value
32
-
33
- Kind::Is.__call__(::%{kind_name_to_check}, value)
34
- end
35
- RUBY
36
-
37
- private_constant :KIND_OF, :KIND_IS, :COLONS
38
-
39
- def add(kind, name: nil)
40
- kind_name = Kind.of.Module(kind).name
41
- checker = name ? Kind::Of.(String, name) : kind_name
42
-
43
- if checker.include?(COLONS)
44
- add_kind_with_namespace(checker, method_name: name)
45
- else
46
- add_root(checker, kind_name, method_name: name,
47
- kind_name_to_check: kind_name,
48
- create_kind_is_mod: false)
49
- end
50
- end
51
-
52
- private
53
-
54
- def add_root(checker, kind_name, method_name:, create_kind_is_mod:, kind_name_to_check: nil)
55
- root_kind_name = method_name ? method_name : kind_name
56
-
57
- params = {
58
- method_name: method_name ? method_name : checker,
59
- kind_name: method_name ? method_name : kind_name,
60
- kind_name_to_check: kind_name_to_check || root_kind_name
61
- }
62
-
63
- add_kind(params, Kind::Of, Kind::Is, create_kind_is_mod)
64
- end
65
-
66
- def add_kind_with_namespace(checker, method_name:)
67
- raise NotImplementedError if method_name
68
-
69
- const_names = checker.split(COLONS)
70
- const_names.each_with_index do |const_name, index|
71
- if index == 0
72
- add_root(const_name, const_name, method_name: nil, create_kind_is_mod: true)
73
- else
74
- add_node(const_names, index)
75
- end
76
- end
77
- end
78
-
79
- def add_node(const_names, index)
80
- namespace = const_names[0..(index-1)]
81
- namespace_name = namespace.join(COLONS)
82
-
83
- kind_of_mod = Kind::Of.const_get(namespace_name)
84
- kind_is_mod = Kind::Is.const_get(namespace_name)
85
-
86
- checker = const_names[index]
87
- kind_name = const_names[0..index].join(COLONS)
88
-
89
- params = { method_name: checker, kind_name: kind_name }
90
-
91
- add_kind(params, kind_of_mod, kind_is_mod, true)
92
- end
93
-
94
- def add_kind(params, kind_of_mod, kind_is_mod, create_kind_is_mod)
95
- method_name = params[:method_name]
96
-
97
- unless kind_of_mod.respond_to?(method_name)
98
- kind_name = params[:kind_name]
99
- params[:kind_name_to_check] ||= kind_name
100
-
101
- kind_checker = ::Module.new { extend Checker::Protocol }
102
- kind_checker.module_eval("def self.__kind; #{params[:kind_name_to_check]}; end")
103
-
104
- kind_of_mod.instance_eval(KIND_OF % params)
105
- kind_of_mod.const_set(method_name, kind_checker)
106
- kind_of_mod.instance_eval(KIND_OF_IS % params)
107
- end
108
-
109
- unless kind_is_mod.respond_to?(method_name)
110
- kind_is_mod.instance_eval(KIND_IS % params)
111
- kind_is_mod.const_set(method_name, Module.new) if create_kind_is_mod
112
- end
113
- end
114
- end
115
- end