kind 3.0.1 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
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