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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -0
  3. data/.travis.sh +37 -12
  4. data/.travis.yml +6 -3
  5. data/CHANGELOG.md +1230 -0
  6. data/Gemfile +10 -2
  7. data/README.md +817 -487
  8. data/lib/kind.rb +53 -283
  9. data/lib/kind/active_model/kind_validator.rb +7 -7
  10. data/lib/kind/core.rb +9 -0
  11. data/lib/kind/core/deprecation.rb +29 -0
  12. data/lib/kind/core/kind.rb +61 -0
  13. data/lib/kind/core/undefined.rb +7 -0
  14. data/lib/kind/deprecations/built_in_type_checkers.rb +23 -0
  15. data/lib/kind/{checker.rb → deprecations/checker.rb} +3 -2
  16. data/lib/kind/{checker → deprecations/checker}/factory.rb +1 -5
  17. data/lib/kind/{checker → deprecations/checker}/protocol.rb +3 -3
  18. data/lib/kind/deprecations/is.rb +35 -0
  19. data/lib/kind/deprecations/of.rb +258 -0
  20. data/lib/kind/{types.rb → deprecations/types.rb} +14 -8
  21. data/lib/kind/dig.rb +13 -9
  22. data/lib/kind/empty.rb +5 -11
  23. data/lib/kind/error.rb +2 -6
  24. data/lib/kind/maybe.rb +12 -161
  25. data/lib/kind/maybe/none.rb +57 -0
  26. data/lib/kind/maybe/result.rb +51 -0
  27. data/lib/kind/maybe/some.rb +90 -0
  28. data/lib/kind/maybe/typed.rb +29 -0
  29. data/lib/kind/maybe/wrappable.rb +35 -0
  30. data/lib/kind/presence.rb +33 -0
  31. data/lib/kind/try.rb +36 -0
  32. data/lib/kind/type_checker.rb +73 -0
  33. data/lib/kind/type_checkers.rb +30 -0
  34. data/lib/kind/type_checkers/core/array.rb +17 -0
  35. data/lib/kind/type_checkers/core/class.rb +13 -0
  36. data/lib/kind/type_checkers/core/comparable.rb +13 -0
  37. data/lib/kind/type_checkers/core/enumerable.rb +13 -0
  38. data/lib/kind/type_checkers/core/enumerator.rb +13 -0
  39. data/lib/kind/type_checkers/core/file.rb +13 -0
  40. data/lib/kind/type_checkers/core/float.rb +13 -0
  41. data/lib/kind/type_checkers/core/hash.rb +17 -0
  42. data/lib/kind/type_checkers/core/integer.rb +13 -0
  43. data/lib/kind/type_checkers/core/io.rb +13 -0
  44. data/lib/kind/type_checkers/core/method.rb +13 -0
  45. data/lib/kind/type_checkers/core/module.rb +17 -0
  46. data/lib/kind/type_checkers/core/numeric.rb +13 -0
  47. data/lib/kind/type_checkers/core/proc.rb +13 -0
  48. data/lib/kind/type_checkers/core/queue.rb +14 -0
  49. data/lib/kind/type_checkers/core/range.rb +13 -0
  50. data/lib/kind/type_checkers/core/regexp.rb +13 -0
  51. data/lib/kind/type_checkers/core/string.rb +17 -0
  52. data/lib/kind/type_checkers/core/struct.rb +13 -0
  53. data/lib/kind/type_checkers/core/symbol.rb +13 -0
  54. data/lib/kind/type_checkers/core/time.rb +13 -0
  55. data/lib/kind/type_checkers/custom/boolean.rb +19 -0
  56. data/lib/kind/type_checkers/custom/callable.rb +19 -0
  57. data/lib/kind/type_checkers/custom/lambda.rb +19 -0
  58. data/lib/kind/type_checkers/stdlib/open_struct.rb +13 -0
  59. data/lib/kind/type_checkers/stdlib/set.rb +17 -0
  60. data/lib/kind/undefined.rb +4 -2
  61. data/lib/kind/validator.rb +1 -1
  62. data/lib/kind/version.rb +1 -1
  63. data/test.sh +4 -4
  64. metadata +51 -9
  65. data/lib/kind/is.rb +0 -19
  66. 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Class
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Class; end
8
+ end
9
+
10
+ def self.Class?(*values)
11
+ KIND.of?(::Class, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Comparable
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Comparable; end
8
+ end
9
+
10
+ def self.Comparable?(*values)
11
+ KIND.of?(::Comparable, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Enumerable
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Enumerable; end
8
+ end
9
+
10
+ def self.Enumerable?(*values)
11
+ KIND.of?(::Enumerable, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Enumerator
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Enumerator; end
8
+ end
9
+
10
+ def self.Enumerator?(*values)
11
+ KIND.of?(::Enumerator, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module File
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::File; end
8
+ end
9
+
10
+ def self.File?(*values)
11
+ KIND.of?(::File, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Float
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Float; end
8
+ end
9
+
10
+ def self.Float?(*values)
11
+ KIND.of?(::Float, values)
12
+ end
13
+ 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Integer
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Integer; end
8
+ end
9
+
10
+ def self.Integer?(*values)
11
+ KIND.of?(::Integer, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module IO
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::IO; end
8
+ end
9
+
10
+ def self.IO?(*values)
11
+ KIND.of?(::IO, values)
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Method
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Method; end
8
+ end
9
+
10
+ def self.Method?(*values)
11
+ KIND.of?(::Method, values)
12
+ end
13
+ 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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Numeric
5
+ extend self, TypeChecker
6
+
7
+ def kind; ::Numeric; end
8
+ end
9
+
10
+ def self.Numeric?(*values)
11
+ KIND.of?(::Numeric, values)
12
+ end
13
+ end