kind 2.2.0 → 2.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bb8430c79ca97835ebdf6604e0c5afc4301f912db778e5f930fb9e699ae08c1
4
- data.tar.gz: 0557c3df900513e5ec7d45fec79fdf7502f0cb06a8e1538ff935e0228ef11136
3
+ metadata.gz: a234e4c63dea23906a65da0718515bff19ac7934a3e919535596042cfd605bba
4
+ data.tar.gz: 5bcb0f1f669a0e87de070c5095cf8f769ddf97dde4b2169060fb21769ffbd623
5
5
  SHA512:
6
- metadata.gz: 0ad03f0d27484914f45607d9e1fd7cfdaf8000d700e31f069b274b5f977f42a8736a3d03d0cba1f3d06679f0f5a05b56d7c3b4acfd2a90cce20e524de6f9154a
7
- data.tar.gz: 6f8e54590261939a43a52895921d80fb693a0e16361d011f53a80f1d7269aaade1e8871ae44374586ec488c026a02fced9057fdfcb300c532bd3a018498e954a
6
+ metadata.gz: 232d87a65618b51c3ec8756ad9d08bce53a49d50368d4629c8e694050502dddf12cdecd878193e40e09c8fcc13139b1a35383eedaa36a1660f7cf71f7e4d9810
7
+ data.tar.gz: 4cef62a76d8981fa7409e0d598448b35b4bb01794084ad2ab264741cbf0a78e6b9142352369892e124f130750847078f90297e5d1eda955881ebea0f13e96ec7
@@ -3,7 +3,10 @@ language: ruby
3
3
 
4
4
  sudo: false
5
5
 
6
- cache: bundler
6
+ cache:
7
+ bundler: true
8
+ directories:
9
+ - /home/travis/.rvm/
7
10
 
8
11
  rvm:
9
12
  - 2.2.0
data/README.md CHANGED
@@ -39,13 +39,14 @@ One of the goals of this project is to do simple type checking like `"some strin
39
39
  - [Kind.of.\<Type\>.or_undefined()](#kindoftypeor_undefined)
40
40
  - [Kind::Maybe](#kindmaybe)
41
41
  - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas)
42
- - [Kind::Maybe[] and Kind::Maybe#then method aliases](#kindmaybe-and-kindmaybethen-method-aliases)
42
+ - [Kind::Maybe[], Kind::Maybe.wrap() and Kind::Maybe#then method aliases](#kindmaybe-kindmaybewrap-and-kindmaybethen-method-aliases)
43
43
  - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-1)
44
44
  - [Kind::None() and Kind::Some()](#kindnone-and-kindsome)
45
45
  - [Kind.of.Maybe()](#kindofmaybe)
46
46
  - [Kind::Optional](#kindoptional)
47
47
  - [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-2)
48
48
  - [Kind.of.\<Type\>.as_optional](#kindoftypeas_optional)
49
+ - [Kind::Maybe(<Type>)](#kindmaybetype)
49
50
  - [Kind::Maybe#try](#kindmaybetry)
50
51
  - [Kind::Empty](#kindempty)
51
52
  - [Similar Projects](#similar-projects)
@@ -717,7 +718,7 @@ end
717
718
  Kind::Maybe.new(nil).map(&Add).value_or(0) # 0
718
719
  ```
719
720
 
720
- ### Kind::Maybe[] and Kind::Maybe#then method aliases
721
+ ### Kind::Maybe[], Kind::Maybe.wrap() and Kind::Maybe#then method aliases
721
722
 
722
723
  You can use `Kind::Maybe[]` (brackets) instead of the `.new` to transform values in a `Kind::Maybe`. Another alias is `.then` to the `.map` method.
723
724
 
@@ -731,6 +732,19 @@ result =
731
732
  puts result # 42
732
733
  ```
733
734
 
735
+ You can also use `Kind::Maybe.wrap()` instead of the `.new` method.
736
+
737
+ ```ruby
738
+ result =
739
+ Kind::Maybe
740
+ .wrap(5)
741
+ .then { |value| value * 5 }
742
+ .then { |value| value + 17 }
743
+ .value_or(0)
744
+
745
+ puts result # 42
746
+ ```
747
+
734
748
  #### Replacing blocks by lambdas
735
749
 
736
750
  ```ruby
@@ -969,6 +983,46 @@ end
969
983
 
970
984
  [⬆️ Back to Top](#table-of-contents-)
971
985
 
986
+ ### Kind::Maybe(<Type>)
987
+
988
+ There is an alternative to `Kind.of.\<Type\>.as_optional`, you can use `Kind::Optional(<Type>)` to create a maybe monad which will return None if the given input hasn't the expected type. e.g:
989
+
990
+ ```ruby
991
+ result1 =
992
+ Kind::Maybe(Numeric)
993
+ .wrap(5)
994
+ .then { |value| value * 5 }
995
+ .value_or { 0 }
996
+
997
+ puts result1 # 25
998
+
999
+ # ---
1000
+
1001
+ result2 =
1002
+ Kind::Optional(Numeric)
1003
+ .wrap('5')
1004
+ .then { |value| value * 5 }
1005
+ .value_or { 0 }
1006
+
1007
+ puts result2 # 0
1008
+ ```
1009
+
1010
+ This typed maybe has the same methods of `Kind::Maybe` class. e.g:
1011
+
1012
+ ```ruby
1013
+ Kind::Maybe(Numeric)[5]
1014
+ Kind::Maybe(Numeric).new(5)
1015
+ Kind::Maybe(Numeric).wrap(5)
1016
+
1017
+ # ---
1018
+
1019
+ Kind::Optional(Numeric)[5]
1020
+ Kind::Optional(Numeric).new(5)
1021
+ Kind::Optional(Numeric).wrap(5)
1022
+ ```
1023
+
1024
+ [⬆️ Back to Top](#table-of-contents-)
1025
+
972
1026
  ### Kind::Maybe#try
973
1027
 
974
1028
  If you don't want to use a map to access the value, you could use the `#try` method to access it. So, if the value wasn't `nil` or `Kind::Undefined`, it will be returned.
@@ -4,12 +4,12 @@ require 'kind/version'
4
4
 
5
5
  require 'kind/empty'
6
6
  require 'kind/undefined'
7
+ require 'kind/checker'
7
8
  require 'kind/maybe'
8
9
 
9
10
  require 'kind/error'
10
11
  require 'kind/of'
11
12
  require 'kind/is'
12
- require 'kind/checker'
13
13
  require 'kind/types'
14
14
 
15
15
  module Kind
@@ -25,30 +25,12 @@ module Kind
25
25
  raise ArgumentError, WRONG_NUMBER_OF_ARGUMENTS
26
26
  end
27
27
 
28
- MODULE_OR_CLASS = 'Module/Class'.freeze
29
-
30
- private_constant :MODULE_OR_CLASS
31
-
32
- private_class_method def self.__checkers__
33
- @__checkers__ ||= {}
34
- end
35
-
36
- __checkers__
37
-
38
28
  def self.of(kind = Undefined, object = Undefined)
39
29
  return Of if Undefined == kind && Undefined == object
40
30
 
41
31
  return Kind::Of.(kind, object) if Undefined != object
42
32
 
43
- __checkers__[kind] ||= begin
44
- kind_name = kind.name
45
-
46
- if Kind::Of.const_defined?(kind_name, false)
47
- Kind::Of.const_get(kind_name)
48
- else
49
- Checker.new(Kind::Of.(Module, kind, MODULE_OR_CLASS))
50
- end
51
- end
33
+ Kind::Checker::Factory.create(kind)
52
34
  end
53
35
 
54
36
  def self.of?(kind, *args)
@@ -87,7 +69,7 @@ module Kind
87
69
  end
88
70
 
89
71
  const_set(:Class, ::Module.new do
90
- extend Checkable
72
+ extend Checker::Protocol
91
73
 
92
74
  def self.__kind; ::Class; end
93
75
 
@@ -109,7 +91,7 @@ module Kind
109
91
  end
110
92
 
111
93
  const_set(:Module, ::Module.new do
112
- extend Checkable
94
+ extend Checker::Protocol
113
95
 
114
96
  def self.__kind_undefined(value)
115
97
  __kind_error(Kind::Undefined) if Kind::Undefined == value
@@ -165,7 +147,7 @@ module Kind
165
147
  end
166
148
 
167
149
  const_set(:Boolean, ::Module.new do
168
- extend Checkable
150
+ extend Checker::Protocol
169
151
 
170
152
  def self.__kind; [TrueClass, FalseClass].freeze; end
171
153
 
@@ -220,7 +202,7 @@ module Kind
220
202
  end
221
203
 
222
204
  const_set(:Lambda, ::Module.new do
223
- extend Checkable
205
+ extend Checker::Protocol
224
206
 
225
207
  def self.__kind; ::Proc; end
226
208
 
@@ -268,7 +250,7 @@ module Kind
268
250
  end
269
251
 
270
252
  const_set(:Callable, ::Module.new do
271
- extend Checkable
253
+ extend Checker::Protocol
272
254
 
273
255
  def self.__kind; Object; end
274
256
 
@@ -1,78 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kind/checker/factory'
4
+ require 'kind/checker/protocol'
3
5
  module Kind
4
- module Checkable
5
- def class?(value)
6
- Kind::Is.__call__(__kind, value)
7
- end
8
-
9
- def instance(value, options = Empty::HASH)
10
- default = options[:or]
11
-
12
- return Kind::Of.(__kind, value) if ::Kind::Maybe::Value.none?(default)
13
-
14
- Kind::Undefined != value && instance?(value) ? value : Kind::Of.(__kind, default)
15
- end
16
-
17
- def [](value, options = options = Empty::HASH)
18
- instance(value, options)
19
- end
20
-
21
- def to_proc
22
- @to_proc ||=
23
- -> checker { -> value { checker.instance(value) } }.call(self)
24
- end
25
-
26
- def __is_instance__(value)
27
- value.kind_of?(__kind)
28
- end
29
-
30
- def is_instance_to_proc
31
- @is_instance_to_proc ||=
32
- -> checker { -> value { checker.__is_instance__(value) } }.call(self)
33
- end
34
-
35
- def instance?(*args)
36
- return is_instance_to_proc if args.empty?
37
-
38
- return args.all? { |object| __is_instance__(object) } if args.size > 1
39
-
40
- arg = args[0]
41
- Kind::Undefined == arg ? is_instance_to_proc : __is_instance__(arg)
42
- end
43
-
44
- def or_nil(value)
45
- return value if instance?(value)
46
- end
47
-
48
- def or_undefined(value)
49
- or_nil(value) || Kind::Undefined
50
- end
51
-
52
- def __as_maybe__(value)
53
- Kind::Maybe.new(or_nil(value))
54
- end
55
-
56
- def as_maybe_to_proc
57
- @as_maybe_to_proc ||=
58
- -> checker { -> value { checker.__as_maybe__(value) } }.call(self)
59
- end
60
-
61
- def as_maybe(value = Kind::Undefined)
62
- return __as_maybe__(value) if Kind::Undefined != value
63
-
64
- as_maybe_to_proc
65
- end
66
-
67
- def as_optional(value = Kind::Undefined)
68
- as_maybe(value)
69
- end
70
- end
71
-
72
- private_constant :Checkable
73
-
74
6
  class Checker
75
- include Checkable
7
+ include Protocol
76
8
 
77
9
  attr_reader :__kind
78
10
 
@@ -0,0 +1,35 @@
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
@@ -0,0 +1,73 @@
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
@@ -2,6 +2,19 @@
2
2
 
3
3
  module Kind
4
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
+
5
18
  module Value
6
19
  def self.none?(value)
7
20
  value.nil? || Undefined == value
@@ -102,7 +115,11 @@ module Kind
102
115
  result_type.new(value)
103
116
  end
104
117
 
105
- def self.[](value);
118
+ def self.[](value)
119
+ new(value)
120
+ end
121
+
122
+ def self.wrap(value)
106
123
  new(value)
107
124
  end
108
125
 
@@ -132,4 +149,12 @@ module Kind
132
149
  def self.Some(value)
133
150
  Maybe.some(value)
134
151
  end
152
+
153
+ def self.Maybe(kind)
154
+ Maybe::Typed.new(kind)
155
+ end
156
+
157
+ def self.Optional(kind)
158
+ Maybe::Typed.new(kind)
159
+ end
135
160
  end
@@ -98,7 +98,7 @@ module Kind
98
98
  kind_name = params[:kind_name]
99
99
  params[:kind_name_to_check] ||= kind_name
100
100
 
101
- kind_checker = ::Module.new { extend Checkable }
101
+ kind_checker = ::Module.new { extend Checker::Protocol }
102
102
  kind_checker.module_eval("def self.__kind; #{params[:kind_name_to_check]}; end")
103
103
 
104
104
  kind_of_mod.instance_eval(KIND_OF % params)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '2.2.0'
4
+ VERSION = '2.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kind
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
11
+ date: 2020-06-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple type system (at runtime) for Ruby - free of dependencies.
14
14
  email:
@@ -32,6 +32,8 @@ files:
32
32
  - lib/kind/active_model/kind_validator.rb
33
33
  - lib/kind/active_model/validation.rb
34
34
  - lib/kind/checker.rb
35
+ - lib/kind/checker/factory.rb
36
+ - lib/kind/checker/protocol.rb
35
37
  - lib/kind/empty.rb
36
38
  - lib/kind/error.rb
37
39
  - lib/kind/is.rb