kind 3.1.0 → 4.0.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 +4 -4
- data/.tool-versions +1 -0
- data/.travis.sh +37 -12
- data/.travis.yml +6 -3
- data/CHANGELOG.md +1230 -0
- data/Gemfile +10 -2
- data/README.md +817 -487
- data/lib/kind.rb +53 -283
- data/lib/kind/active_model/kind_validator.rb +7 -7
- data/lib/kind/core.rb +9 -0
- data/lib/kind/core/deprecation.rb +29 -0
- data/lib/kind/core/kind.rb +61 -0
- data/lib/kind/core/undefined.rb +7 -0
- data/lib/kind/deprecations/built_in_type_checkers.rb +23 -0
- data/lib/kind/{checker.rb → deprecations/checker.rb} +3 -2
- data/lib/kind/{checker → deprecations/checker}/factory.rb +1 -5
- data/lib/kind/{checker → deprecations/checker}/protocol.rb +3 -3
- data/lib/kind/deprecations/is.rb +35 -0
- data/lib/kind/deprecations/of.rb +258 -0
- data/lib/kind/{types.rb → deprecations/types.rb} +14 -8
- data/lib/kind/dig.rb +13 -9
- data/lib/kind/empty.rb +5 -11
- data/lib/kind/error.rb +2 -6
- data/lib/kind/maybe.rb +12 -161
- data/lib/kind/maybe/none.rb +57 -0
- data/lib/kind/maybe/result.rb +51 -0
- data/lib/kind/maybe/some.rb +90 -0
- data/lib/kind/maybe/typed.rb +29 -0
- data/lib/kind/maybe/wrappable.rb +35 -0
- data/lib/kind/presence.rb +33 -0
- data/lib/kind/try.rb +36 -0
- data/lib/kind/type_checker.rb +73 -0
- data/lib/kind/type_checkers.rb +30 -0
- data/lib/kind/type_checkers/core/array.rb +17 -0
- data/lib/kind/type_checkers/core/class.rb +13 -0
- data/lib/kind/type_checkers/core/comparable.rb +13 -0
- data/lib/kind/type_checkers/core/enumerable.rb +13 -0
- data/lib/kind/type_checkers/core/enumerator.rb +13 -0
- data/lib/kind/type_checkers/core/file.rb +13 -0
- data/lib/kind/type_checkers/core/float.rb +13 -0
- data/lib/kind/type_checkers/core/hash.rb +17 -0
- data/lib/kind/type_checkers/core/integer.rb +13 -0
- data/lib/kind/type_checkers/core/io.rb +13 -0
- data/lib/kind/type_checkers/core/method.rb +13 -0
- data/lib/kind/type_checkers/core/module.rb +17 -0
- data/lib/kind/type_checkers/core/numeric.rb +13 -0
- data/lib/kind/type_checkers/core/proc.rb +13 -0
- data/lib/kind/type_checkers/core/queue.rb +14 -0
- data/lib/kind/type_checkers/core/range.rb +13 -0
- data/lib/kind/type_checkers/core/regexp.rb +13 -0
- data/lib/kind/type_checkers/core/string.rb +17 -0
- data/lib/kind/type_checkers/core/struct.rb +13 -0
- data/lib/kind/type_checkers/core/symbol.rb +13 -0
- data/lib/kind/type_checkers/core/time.rb +13 -0
- data/lib/kind/type_checkers/custom/boolean.rb +19 -0
- data/lib/kind/type_checkers/custom/callable.rb +19 -0
- data/lib/kind/type_checkers/custom/lambda.rb +19 -0
- data/lib/kind/type_checkers/stdlib/open_struct.rb +13 -0
- data/lib/kind/type_checkers/stdlib/set.rb +17 -0
- data/lib/kind/undefined.rb +4 -2
- data/lib/kind/validator.rb +1 -1
- data/lib/kind/version.rb +1 -1
- data/test.sh +4 -4
- metadata +51 -9
- data/lib/kind/is.rb +0 -19
- data/lib/kind/of.rb +0 -11
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Maybe
|
5
|
+
class Typed
|
6
|
+
include Wrappable
|
7
|
+
|
8
|
+
def initialize(kind)
|
9
|
+
@kind = kind
|
10
|
+
end
|
11
|
+
|
12
|
+
def new(arg)
|
13
|
+
value = Result::Value.(arg)
|
14
|
+
|
15
|
+
value.kind_of?(@kind) ? Maybe.some(value) : Maybe.none
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :[], :new
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def __call_before_expose_the_arg_in_a_block(arg)
|
23
|
+
value = Result::Value.(arg)
|
24
|
+
|
25
|
+
value.kind_of?(@kind) ? value : Maybe.none
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Maybe
|
5
|
+
module Wrappable
|
6
|
+
WRONG_NUMBER_OF_ARGS = 'wrong number of arguments (given 0, expected 1)'.freeze
|
7
|
+
|
8
|
+
def wrap(arg = UNDEFINED)
|
9
|
+
if block_given?
|
10
|
+
begin
|
11
|
+
return new(yield) if UNDEFINED == arg
|
12
|
+
|
13
|
+
input = __call_before_expose_the_arg_in_a_block(arg)
|
14
|
+
|
15
|
+
input.kind_of?(Kind::Maybe::None) ? input : new(yield(input))
|
16
|
+
rescue StandardError => exception
|
17
|
+
Maybe.__none__(exception)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
return new(arg) if UNDEFINED != arg
|
21
|
+
|
22
|
+
raise ArgumentError, WRONG_NUMBER_OF_ARGS
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def __call_before_expose_the_arg_in_a_block(input)
|
29
|
+
input
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private_constant :Wrappable
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Presence
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def call(object)
|
8
|
+
return object.blank? ? nil : object if object.respond_to?(:blank?)
|
9
|
+
|
10
|
+
return object if TrueClass === object
|
11
|
+
|
12
|
+
return blank_str?(object) ? nil : object if String === object
|
13
|
+
|
14
|
+
return object.empty? ? nil : object if object.respond_to?(:empty?)
|
15
|
+
|
16
|
+
return object if object
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_proc
|
20
|
+
-> object { call(object) }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
BLANK_RE = /\A[[:space:]]*\z/
|
26
|
+
|
27
|
+
def blank_str?(object)
|
28
|
+
object.empty? || BLANK_RE === object
|
29
|
+
end
|
30
|
+
|
31
|
+
private_constant :BLANK_RE
|
32
|
+
end
|
33
|
+
end
|
data/lib/kind/try.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Try
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def call(*args)
|
8
|
+
object = args.shift
|
9
|
+
|
10
|
+
call!(object, args.shift, args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.[](*args)
|
14
|
+
Array[args]
|
15
|
+
|
16
|
+
method_name = args.shift
|
17
|
+
|
18
|
+
->(object) { call!(object, method_name, args) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def call!(object, method_name, args) # :nodoc
|
22
|
+
return if KIND.null?(object)
|
23
|
+
|
24
|
+
resolve(object, method_name, args)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def resolve(object, method_name, args = Empty::ARRAY)
|
30
|
+
return unless object.respond_to?(method_name)
|
31
|
+
return object.public_send(method_name) if args.empty?
|
32
|
+
|
33
|
+
object.public_send(method_name, *args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module TypeChecker
|
5
|
+
def name
|
6
|
+
kind.name
|
7
|
+
end
|
8
|
+
|
9
|
+
def ===(value)
|
10
|
+
kind === value
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](value)
|
14
|
+
return value if self === value
|
15
|
+
|
16
|
+
KIND.error!(name, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def or_nil(value)
|
20
|
+
return value if self === value
|
21
|
+
end
|
22
|
+
|
23
|
+
def or_undefined(value)
|
24
|
+
or_nil(value) || Undefined
|
25
|
+
end
|
26
|
+
|
27
|
+
def or(fallback, value = UNDEFINED)
|
28
|
+
return __or_func.(fallback) if UNDEFINED === value
|
29
|
+
|
30
|
+
self === value ? value : fallback
|
31
|
+
end
|
32
|
+
|
33
|
+
def value?(value = UNDEFINED)
|
34
|
+
return self === value if UNDEFINED != value
|
35
|
+
|
36
|
+
@__is_value ||= ->(ck) { ->(value) { ck === value } }.(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def value(arg, default:)
|
40
|
+
KIND.value(self, arg, self[default])
|
41
|
+
end
|
42
|
+
|
43
|
+
def or_null(value) # :nodoc:
|
44
|
+
KIND.null?(value) ? value : self[value]
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def __or_func
|
50
|
+
@__or_func ||= ->(tc, fb, value) { tc === value ? value : tc.or_null(fb) }.curry[self]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class TypeChecker::Object # :nodoc: all
|
55
|
+
include TypeChecker
|
56
|
+
|
57
|
+
ResolveKindName = ->(kind, opt) do
|
58
|
+
name = Try.(opt, :[], :name)
|
59
|
+
name || Try.(kind, :name)
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :kind, :name
|
63
|
+
|
64
|
+
def initialize(kind, opt)
|
65
|
+
name = ResolveKindName.(kind, opt)
|
66
|
+
|
67
|
+
@name = KIND.of!(::String, name)
|
68
|
+
@kind = KIND.respond_to!(:===, kind)
|
69
|
+
end
|
70
|
+
|
71
|
+
private_constant :ResolveKindName
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/type_checkers/core/array'
|
4
|
+
require 'kind/type_checkers/core/class'
|
5
|
+
require 'kind/type_checkers/core/comparable'
|
6
|
+
require 'kind/type_checkers/core/enumerable'
|
7
|
+
require 'kind/type_checkers/core/enumerator'
|
8
|
+
require 'kind/type_checkers/core/file'
|
9
|
+
require 'kind/type_checkers/core/float'
|
10
|
+
require 'kind/type_checkers/core/hash'
|
11
|
+
require 'kind/type_checkers/core/integer'
|
12
|
+
require 'kind/type_checkers/core/io'
|
13
|
+
require 'kind/type_checkers/core/module'
|
14
|
+
require 'kind/type_checkers/core/method'
|
15
|
+
require 'kind/type_checkers/core/numeric'
|
16
|
+
require 'kind/type_checkers/core/proc'
|
17
|
+
require 'kind/type_checkers/core/queue'
|
18
|
+
require 'kind/type_checkers/core/range'
|
19
|
+
require 'kind/type_checkers/core/regexp'
|
20
|
+
require 'kind/type_checkers/core/string'
|
21
|
+
require 'kind/type_checkers/core/struct'
|
22
|
+
require 'kind/type_checkers/core/symbol'
|
23
|
+
require 'kind/type_checkers/core/time'
|
24
|
+
|
25
|
+
require 'kind/type_checkers/stdlib/open_struct'
|
26
|
+
require 'kind/type_checkers/stdlib/set'
|
27
|
+
|
28
|
+
require 'kind/type_checkers/custom/boolean'
|
29
|
+
require 'kind/type_checkers/custom/callable'
|
30
|
+
require 'kind/type_checkers/custom/lambda'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Array
|
5
|
+
extend self, TypeChecker
|
6
|
+
|
7
|
+
def kind; ::Array; end
|
8
|
+
|
9
|
+
def value_or_empty(arg)
|
10
|
+
KIND.value(self, arg, Empty::ARRAY)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.Array?(*values)
|
15
|
+
KIND.of?(::Array, values)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Hash
|
5
|
+
extend self, TypeChecker
|
6
|
+
|
7
|
+
def kind; ::Hash; end
|
8
|
+
|
9
|
+
def value_or_empty(arg)
|
10
|
+
KIND.value(self, arg, Empty::HASH)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.Hash?(*values)
|
15
|
+
KIND.of?(::Hash, values)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Module
|
5
|
+
extend self, TypeChecker
|
6
|
+
|
7
|
+
def kind; ::Module; end
|
8
|
+
|
9
|
+
def ===(value)
|
10
|
+
Kind.of_module?(value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.Module?(*values)
|
15
|
+
KIND.of?(::Kind::Module, values)
|
16
|
+
end
|
17
|
+
end
|