kind 4.0.0 → 5.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 +4 -4
- data/.tool-versions +1 -1
- data/.travis.sh +39 -7
- data/.travis.yml +1 -2
- data/CHANGELOG.md +486 -28
- data/Gemfile +13 -6
- data/README.md +153 -49
- data/kind.gemspec +1 -1
- data/lib/kind.rb +2 -84
- data/lib/kind/__lib__/action_steps.rb +57 -0
- data/lib/kind/__lib__/attributes.rb +66 -0
- data/lib/kind/__lib__/kind.rb +51 -0
- data/lib/kind/__lib__/of.rb +17 -0
- data/lib/kind/__lib__/strict.rb +49 -0
- data/lib/kind/__lib__/undefined.rb +14 -0
- data/lib/kind/action.rb +127 -0
- data/lib/kind/active_model/validation.rb +3 -4
- data/lib/kind/basic.rb +79 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
- data/lib/kind/dig.rb +21 -5
- data/lib/kind/either.rb +30 -0
- data/lib/kind/either/left.rb +29 -0
- data/lib/kind/either/methods.rb +17 -0
- data/lib/kind/either/monad.rb +65 -0
- data/lib/kind/either/monad/wrapper.rb +19 -0
- data/lib/kind/either/right.rb +38 -0
- data/lib/kind/empty.rb +2 -2
- data/lib/kind/empty/constant.rb +7 -0
- data/lib/kind/enum.rb +63 -0
- data/lib/kind/enum/item.rb +40 -0
- data/lib/kind/enum/methods.rb +72 -0
- data/lib/kind/function.rb +45 -0
- data/lib/kind/functional.rb +89 -0
- data/lib/kind/functional/action.rb +90 -0
- data/lib/kind/immutable_attributes.rb +34 -0
- data/lib/kind/immutable_attributes/initializer.rb +70 -0
- data/lib/kind/immutable_attributes/reader.rb +38 -0
- data/lib/kind/maybe.rb +37 -12
- data/lib/kind/maybe/methods.rb +21 -0
- data/lib/kind/maybe/monad.rb +82 -0
- data/lib/kind/maybe/monad/wrapper.rb +19 -0
- data/lib/kind/maybe/none.rb +12 -19
- data/lib/kind/maybe/some.rb +68 -26
- data/lib/kind/maybe/typed.rb +11 -5
- data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +9 -7
- data/lib/kind/monad.rb +22 -0
- data/lib/kind/monads.rb +5 -0
- data/lib/kind/objects.rb +17 -0
- data/lib/kind/objects/basic_object.rb +43 -0
- data/lib/kind/objects/modules.rb +32 -0
- data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
- data/lib/kind/objects/nil.rb +17 -0
- data/lib/kind/objects/not_nil.rb +9 -0
- data/lib/kind/objects/object.rb +56 -0
- data/lib/kind/objects/respond_to.rb +30 -0
- data/lib/kind/objects/union_type.rb +44 -0
- data/lib/kind/presence.rb +4 -2
- data/lib/kind/result.rb +31 -0
- data/lib/kind/result/abstract.rb +53 -0
- data/lib/kind/result/failure.rb +33 -0
- data/lib/kind/result/methods.rb +17 -0
- data/lib/kind/result/monad.rb +74 -0
- data/lib/kind/result/monad/wrapper.rb +19 -0
- data/lib/kind/result/success.rb +53 -0
- data/lib/kind/strict/disabled.rb +34 -0
- data/lib/kind/try.rb +21 -11
- data/lib/kind/validator.rb +111 -0
- data/lib/kind/version.rb +1 -1
- metadata +78 -48
- data/lib/kind/active_model/kind_validator.rb +0 -96
- data/lib/kind/core.rb +0 -9
- data/lib/kind/core/deprecation.rb +0 -29
- data/lib/kind/core/kind.rb +0 -61
- data/lib/kind/core/undefined.rb +0 -7
- data/lib/kind/deprecations/built_in_type_checkers.rb +0 -23
- data/lib/kind/deprecations/checker.rb +0 -16
- data/lib/kind/deprecations/checker/factory.rb +0 -31
- data/lib/kind/deprecations/checker/protocol.rb +0 -73
- data/lib/kind/deprecations/is.rb +0 -35
- data/lib/kind/deprecations/of.rb +0 -258
- data/lib/kind/deprecations/types.rb +0 -121
- data/lib/kind/error.rb +0 -15
- data/lib/kind/maybe/result.rb +0 -51
- data/lib/kind/type_checker.rb +0 -73
- data/lib/kind/type_checkers.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b826449cc89c4cd8dc3d58694a37914f7de37cb7000a2ba534ffa914f10f7677
|
4
|
+
data.tar.gz: e2ed88bcf83d332de58a8516533a58f858494e7ac2ea60f58517e08cd11066c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac5f74a2ba85be82a6b9709745069047105ccdf8aacadbabdb7e96f66ff007dd0e7ce8e2001df206614c3bf852cb95f3c9d21d2f203490a39070a92bb2250afd
|
7
|
+
data.tar.gz: 14b4f8b747a25b9c9535f40972dcfbc07116f97051090616053c663dbfe71cc5b8771bc5899da4e51a77168acb18a18a8c0b898a37c6730397d5c3a4afdc340b
|
data/.tool-versions
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby
|
1
|
+
ruby 3.0.0
|
data/.travis.sh
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
RUBY_V=$(ruby -v)
|
4
4
|
|
5
|
+
function run_basic_tests {
|
6
|
+
if [ ! -z "$1" ]; then
|
7
|
+
bundle_cmd="bundle _$1_"
|
8
|
+
else
|
9
|
+
bundle_cmd="bundle"
|
10
|
+
fi
|
11
|
+
|
12
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{basic/*_test,basic_test}.rb'"
|
13
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/enum_test.rb'"
|
14
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/presence_test.rb'"
|
15
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/dig_test.rb'"
|
16
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/try_test.rb'"
|
17
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/maybe_test.rb'"
|
18
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/immutable_attributes_test.rb'"
|
19
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/function_test.rb'"
|
20
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/action_test.rb'"
|
21
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{functional/*_test,functional_test}.rb'"
|
22
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/either/*_test.rb'"
|
23
|
+
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/result/*_test.rb'"
|
24
|
+
|
25
|
+
eval "KIND_STRICT=t $bundle_cmd exec rake test TEST='test/kind/strict_disabled_test.rb'"
|
26
|
+
}
|
27
|
+
|
5
28
|
function run_with_bundler {
|
6
29
|
rm Gemfile.lock
|
7
30
|
|
@@ -19,12 +42,17 @@ function run_with_am_version_and_bundler {
|
|
19
42
|
run_with_bundler "$2" "ACTIVEMODEL_VERSION=$1"
|
20
43
|
}
|
21
44
|
|
45
|
+
RUBY_2_12="ruby 2.[12]."
|
22
46
|
RUBY_2_2345="ruby 2.[2345]."
|
47
|
+
RUBY_2_12345="ruby 2.[12345]."
|
48
|
+
RUBY_2_567="ruby 2.[567]."
|
49
|
+
RUBY_3_0="ruby 3.0."
|
23
50
|
|
24
|
-
if [[ $RUBY_V =~ $
|
25
|
-
run_with_bundler "$BUNDLER_V1"
|
26
|
-
|
51
|
+
if [[ $RUBY_V =~ $RUBY_2_12 ]]; then
|
27
52
|
run_with_am_version_and_bundler "3.2" "$BUNDLER_V1"
|
53
|
+
fi
|
54
|
+
|
55
|
+
if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
28
56
|
run_with_am_version_and_bundler "4.0" "$BUNDLER_V1"
|
29
57
|
run_with_am_version_and_bundler "4.1" "$BUNDLER_V1"
|
30
58
|
run_with_am_version_and_bundler "4.2" "$BUNDLER_V1"
|
@@ -33,13 +61,17 @@ if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
|
33
61
|
run_with_am_version_and_bundler "5.2" "$BUNDLER_V1"
|
34
62
|
fi
|
35
63
|
|
36
|
-
|
37
|
-
|
64
|
+
if [[ $RUBY_V =~ $RUBY_2_12345 ]]; then
|
65
|
+
run_basic_tests "$BUNDLER_V1"
|
66
|
+
run_with_bundler "$BUNDLER_V1"
|
67
|
+
fi
|
38
68
|
|
39
|
-
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $
|
69
|
+
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $RUBY_3_0 ]]; then
|
40
70
|
gem install bundler -v ">= 2" --no-doc
|
41
71
|
|
42
|
-
run_with_bundler
|
43
72
|
run_with_am_version_and_bundler "6.0"
|
44
73
|
run_with_am_version_and_bundler "6.1"
|
74
|
+
|
75
|
+
run_basic_tests
|
76
|
+
run_with_bundler
|
45
77
|
fi
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,61 +3,75 @@
|
|
3
3
|
This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the recommendations of [keepachangelog.com](http://keepachangelog.com/).
|
4
4
|
|
5
5
|
- [Unreleased](#unreleased)
|
6
|
-
- [
|
6
|
+
- [5.3.0 (2021-03-23)](#530-2021-03-23)
|
7
7
|
- [Added](#added)
|
8
|
-
|
9
|
-
- [Fixed](#fixed)
|
10
|
-
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
8
|
+
- [5.2.0 (2021-03-17)](#520-2021-03-17)
|
11
9
|
- [Added](#added-1)
|
12
|
-
- [
|
13
|
-
- [
|
10
|
+
- [Deprecated](#deprecated)
|
11
|
+
- [Changes](#changes)
|
12
|
+
- [5.1.0 (2021-02-23)](#510-2021-02-23)
|
14
13
|
- [Added](#added-2)
|
15
|
-
- [
|
14
|
+
- [Deprecated](#deprecated-1)
|
15
|
+
- [5.0.0 (2021-02-22)](#500-2021-02-22)
|
16
|
+
- [Breaking Changes](#breaking-changes)
|
17
|
+
- [Removed](#removed)
|
18
|
+
- [4.1.0 (2021-02-22)](#410-2021-02-22)
|
16
19
|
- [Added](#added-3)
|
17
|
-
- [
|
20
|
+
- [4.0.0 (2021-02-22)](#400-2021-02-22)
|
18
21
|
- [Added](#added-4)
|
19
|
-
- [
|
22
|
+
- [Deprecated](#deprecated-2)
|
23
|
+
- [Fixed](#fixed)
|
24
|
+
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
20
25
|
- [Added](#added-5)
|
26
|
+
- [3.0.0 (2020-06-25)](#300-2020-06-25)
|
21
27
|
- [Breaking Changes](#breaking-changes-1)
|
22
|
-
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
23
28
|
- [Added](#added-6)
|
29
|
+
- [2.3.0 (2020-06-24)](#230-2020-06-24)
|
30
|
+
- [Added](#added-7)
|
31
|
+
- [2.2.0 (2020-06-23)](#220-2020-06-23)
|
32
|
+
- [Added](#added-8)
|
33
|
+
- [2.1.0 (2020-05-12)](#210-2020-05-12)
|
34
|
+
- [Added](#added-9)
|
24
35
|
- [Breaking Changes](#breaking-changes-2)
|
25
|
-
|
36
|
+
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
37
|
+
- [Added](#added-10)
|
38
|
+
- [Breaking Changes](#breaking-changes-3)
|
39
|
+
- [Removed](#removed-1)
|
26
40
|
- [1.9.0 (2020-05-06)](#190-2020-05-06)
|
27
|
-
- [Added](#added-
|
41
|
+
- [Added](#added-11)
|
28
42
|
- [1.8.0 (2020-05-03)](#180-2020-05-03)
|
29
|
-
- [Added](#added-
|
43
|
+
- [Added](#added-12)
|
30
44
|
- [1.7.0 (2020-05-03)](#170-2020-05-03)
|
31
45
|
- [Fixed](#fixed-1)
|
32
46
|
- [1.6.0 (2020-04-17)](#160-2020-04-17)
|
33
|
-
- [Added](#added-
|
34
|
-
- [Changes](#changes)
|
47
|
+
- [Added](#added-13)
|
48
|
+
- [Changes](#changes-1)
|
35
49
|
- [1.5.0 (2020-04-12)](#150-2020-04-12)
|
36
|
-
- [Added](#added-
|
50
|
+
- [Added](#added-14)
|
37
51
|
- [1.4.0 (2020-04-12)](#140-2020-04-12)
|
38
|
-
- [Added](#added-
|
52
|
+
- [Added](#added-15)
|
39
53
|
- [1.3.0 (2020-04-12)](#130-2020-04-12)
|
40
|
-
- [Added](#added-
|
54
|
+
- [Added](#added-16)
|
41
55
|
- [1.2.0 (2020-04-12)](#120-2020-04-12)
|
42
|
-
- [Added](#added-
|
56
|
+
- [Added](#added-17)
|
43
57
|
- [1.1.0 (2020-04-09)](#110-2020-04-09)
|
44
|
-
- [Added](#added-
|
58
|
+
- [Added](#added-18)
|
45
59
|
- [Fixed](#fixed-2)
|
46
60
|
- [1.0.0 (2020-03-16)](#100-2020-03-16)
|
47
|
-
- [Added](#added-
|
61
|
+
- [Added](#added-19)
|
48
62
|
- [0.6.0 (2020-01-06)](#060-2020-01-06)
|
49
|
-
- [Added](#added-
|
63
|
+
- [Added](#added-20)
|
50
64
|
- [0.5.0 (2020-01-04)](#050-2020-01-04)
|
51
|
-
- [Added](#added-
|
65
|
+
- [Added](#added-21)
|
52
66
|
- [0.4.0 (2020-01-03)](#040-2020-01-03)
|
53
|
-
- [Added](#added-
|
67
|
+
- [Added](#added-22)
|
54
68
|
- [0.3.0 (2020-01-03)](#030-2020-01-03)
|
55
|
-
- [Added](#added-
|
56
|
-
- [Breaking Changes](#breaking-changes-
|
69
|
+
- [Added](#added-23)
|
70
|
+
- [Breaking Changes](#breaking-changes-4)
|
57
71
|
- [0.2.0 (2020-01-02)](#020-2020-01-02)
|
58
|
-
- [Added](#added-
|
72
|
+
- [Added](#added-24)
|
59
73
|
- [0.1.0 (2019-12-26)](#010-2019-12-26)
|
60
|
-
- [Added](#added-
|
74
|
+
- [Added](#added-25)
|
61
75
|
|
62
76
|
## Unreleased
|
63
77
|
|
@@ -69,6 +83,450 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
|
|
69
83
|
### Fixed
|
70
84
|
-->
|
71
85
|
|
86
|
+
5.3.0 (2021-03-23)
|
87
|
+
------------------
|
88
|
+
|
89
|
+
### Added
|
90
|
+
|
91
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Allow `Kind::Result#map` and `Kind::Result#map!` receive a callable as an argument.
|
92
|
+
|
93
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add `|` and `>>` as an alias of `Kind::Result#map!`.
|
94
|
+
|
95
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add step adapters for `Kind::Action` and `Kind::Functional::Action`. This is the list of methods: `Step`, `Map`, `Try`, `Tee`, `Check`.
|
96
|
+
```ruby
|
97
|
+
module CreateUser
|
98
|
+
extend Kind::Functional::Action
|
99
|
+
|
100
|
+
def call!(input)
|
101
|
+
Step!(:validate, input) \
|
102
|
+
| Step(:create)
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def validate(input)
|
108
|
+
# returns Success(valid_data) or Failure(validation)
|
109
|
+
end
|
110
|
+
|
111
|
+
def create(input)
|
112
|
+
# returns Success(user)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add `kind/strict/disabled` to turn off all of the strict validations and optimize the runtime. Use case: As strict validation is useful in development, this mechanism could be used to optimize the runtime in production. List of methods that will be disabled:
|
118
|
+
* `Kind.of()`
|
119
|
+
* `Kind.of_class()`
|
120
|
+
* `Kind.of_module()`
|
121
|
+
* `Kind.of_module_or_class()`
|
122
|
+
* `Kind::<Type>[1]`
|
123
|
+
* `Kind::NotNil[1]`
|
124
|
+
|
125
|
+
5.2.0 (2021-03-17)
|
126
|
+
------------------
|
127
|
+
|
128
|
+
### Added
|
129
|
+
|
130
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind.respond_to?`. This method has two different behaviors, when it receives just one argument it will behave like the native Ruby's
|
131
|
+
`respond_to?` method, that is, it will check if the `Kind` method implements some method. But if it receives two arguments, the first one will be the object, and the others (one or more) will be a list of method names that will be used to check if the given object implements them. e.g.
|
132
|
+
```ruby
|
133
|
+
Kind.respond_to?(:is?) # true
|
134
|
+
|
135
|
+
Kind.respond_to?(:foo?) # true
|
136
|
+
|
137
|
+
# --
|
138
|
+
|
139
|
+
Kind.respond_to?({}, :fetch, :merge) # true
|
140
|
+
|
141
|
+
Kind.respond_to?([], :fetch, :merge) # false
|
142
|
+
```
|
143
|
+
|
144
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::UnionType`. This class allows the creation of an object that knows how to compare a value through different kinds of types. e.g.
|
145
|
+
```ruby
|
146
|
+
# The method [] can build a union type object that will have the method #|
|
147
|
+
# which allows the composition with other object kinds.
|
148
|
+
array_or_hash = Kind::UnionType[Array] | Hash
|
149
|
+
|
150
|
+
# The method === can verify if a given value is one of the kinds that compounds the union type.
|
151
|
+
array_or_hash === {} # true
|
152
|
+
array_or_hash === [] # true
|
153
|
+
array_or_hash === 1 # false
|
154
|
+
array_or_hash === nil # false
|
155
|
+
|
156
|
+
# The method #[] will return the given value if it has one of the expected kinds,
|
157
|
+
# but if not, it will raise a Kind::Error.
|
158
|
+
array_or_hash[{}] # {}
|
159
|
+
|
160
|
+
array_or_hash[1] # Kind::Error (1 expected to be a kind of (Array | Hash))
|
161
|
+
|
162
|
+
# At last, the method #name is an alias to the method #inspect.
|
163
|
+
array_or_hash.name # "(Array | Hash)"
|
164
|
+
array_or_hash.inspect # "(Array | Hash)"
|
165
|
+
```
|
166
|
+
|
167
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Nil`. This module was added to be used to create union types. e.g.
|
168
|
+
```ruby
|
169
|
+
hash_or_nil = Kind::UnionType[Hash] | Kind::Nil
|
170
|
+
|
171
|
+
hash_or_nil === {} # true
|
172
|
+
hash_or_nil === [] # false
|
173
|
+
hash_or_nil === 1 # false
|
174
|
+
hash_or_nil === nil # true
|
175
|
+
```
|
176
|
+
|
177
|
+
* [#46](https://github.com/serradura/kind/pull/46), [#47](https://github.com/serradura/kind/pull/47) - Add `Kind::NotNil`. This module was added to perform a strict verification where the given value will be returned if it is not nil, and if not, a `Kind::Error` will be raised. e.g.
|
178
|
+
```ruby
|
179
|
+
Kind::NotNil[1] # 1
|
180
|
+
|
181
|
+
Kind::NotNil[nil] # Kind::Error (expected to not be nil)
|
182
|
+
|
183
|
+
Kind::NotNil[nil, label: 'Foo#bar'] # Kind::Error (Foo#bar: expected to not be nil)
|
184
|
+
```
|
185
|
+
|
186
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::RespondTo` to create objects that know how to verify if a given object implements one or more expected methods.
|
187
|
+
```ruby
|
188
|
+
HashLike = Kind::RespondTo[:fetch, :merge!]
|
189
|
+
Fetchable = Kind::RespondTo[:fetch]
|
190
|
+
|
191
|
+
# Verifying if an object implements the expected interface.
|
192
|
+
HashLike === ENV # true
|
193
|
+
HashLike === {} # true
|
194
|
+
HashLike === [] # false
|
195
|
+
|
196
|
+
Fetchable === ENV # true
|
197
|
+
Fetchable === [] # true
|
198
|
+
Fetchable === {} # true
|
199
|
+
|
200
|
+
# Performing an strict verification
|
201
|
+
HashLike[ENV] # true
|
202
|
+
HashLike[{}] # true
|
203
|
+
HashLike[Array.new] # false Kind::Error ([] expected to be a kind of Kind::RespondTo[:fetch, :merge!])
|
204
|
+
|
205
|
+
# Creating union types using interfaces
|
206
|
+
HashLikeOrArray = HashLike | Array # Kind::RespondTo[:fetch, :merge!] | Array
|
207
|
+
|
208
|
+
HashLikeOrArray === {} # true
|
209
|
+
HashLikeOrArray === [] # true
|
210
|
+
HashLikeOrArray === ENV # true
|
211
|
+
```
|
212
|
+
|
213
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Unfreeze the output of `Kind::Boolean.kind`.
|
214
|
+
|
215
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Freeze `Kind::UNDEFINED` and define its inspect method.
|
216
|
+
|
217
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::TypeChecker#|` to allow the creation of union types.
|
218
|
+
```ruby
|
219
|
+
StatusLabel = Kind::String | Kind::Symbol
|
220
|
+
|
221
|
+
StatusLabel === :ok # true
|
222
|
+
StatusLabel === 'ok' # true
|
223
|
+
StatusLabel === true # false
|
224
|
+
```
|
225
|
+
|
226
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Allow `Kind.of()` and `Kind::TypeChecker#[]` receive a label.
|
227
|
+
```ruby
|
228
|
+
# Kind.of(<Type>, value, label:)
|
229
|
+
class Person
|
230
|
+
attr_reader :name
|
231
|
+
|
232
|
+
def initialize(name:)
|
233
|
+
@name = Kind.of(String, name, label: 'Person#name')
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
Person.new(name: 'Rodrigo') # #<Person:0x0000... @name="Rodrigo">
|
238
|
+
Person.new(name: :ok) # Kind::Error (Person#name: :ok expected to be a kind of String)
|
239
|
+
|
240
|
+
# Kind<Type>[value, label:]
|
241
|
+
class User
|
242
|
+
attr_reader :name
|
243
|
+
|
244
|
+
def initialize(name:)
|
245
|
+
@name = Kind::String[name, label: 'User#name']
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
User.new(name: 'Rodrigo') # #<User:0x0000... @name="Rodrigo">
|
250
|
+
User.new(name: :ok) # Kind::Error (User#name: :ok expected to be a kind of String)
|
251
|
+
```
|
252
|
+
|
253
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Create `kind/basic` to expose a small set of features to do type handling/verification. This is util if you want to make use only of these features instead of all of the others that are loaded via `require "kind"`. So, use `require "kind/basic"` if you only want these features:
|
254
|
+
* `Kind.is?`
|
255
|
+
* `Kind.of`
|
256
|
+
* `Kind.of?`
|
257
|
+
* `Kind.of_class?`
|
258
|
+
* `Kind.of_module?`
|
259
|
+
* `Kind.of_module_or_class`
|
260
|
+
* `Kind.respond_to`
|
261
|
+
* `Kind.respond_to?`
|
262
|
+
* `Kind.value`
|
263
|
+
* `Kind::Error`
|
264
|
+
* `Kind::Undefined`
|
265
|
+
|
266
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Improve `Kind::Maybe`.
|
267
|
+
* Improve the `#inspect` output.
|
268
|
+
* Make `Kind::Maybe.{new,[],wrap}` return `None` if they receive an exception instance.
|
269
|
+
* Add `#accept` as an alias of `#check` method.
|
270
|
+
* Add `#reject` as the reverse of the methods `#check` and `#accept`.
|
271
|
+
* Allow the methods `#map`, `#map!`, `#then`, `#then!`, `#check`, `#accept`, `#reject` to receive one symbol as an argument, it will be used to perform the correspondent method in the `Maybe` value, so if the object responds to the expected method a `Some` will be returned.
|
272
|
+
* Add `Kind::Maybe#on`, this method allows you to use a block where will be possible to define a `Some` or `None` handling. The output of the matched result (some or none) will be the block's output.
|
273
|
+
```ruby
|
274
|
+
# Kind::Maybe#accept (an alias of Kind::Maybe#check)
|
275
|
+
Kind::Maybe[1].accept(&:odd?) # #<Kind::Some value=1>
|
276
|
+
Kind::Maybe[1].accept(&:even?) # #<Kind::None value=nil>
|
277
|
+
|
278
|
+
# Kind::Maybe#reject (the reverse of Kind::Maybe#check)
|
279
|
+
Kind::Maybe[1].reject(&:odd?) # #<Kind::None value=nil>
|
280
|
+
Kind::Maybe[1].reject(&:even?) # #<Kind::Some value=1>
|
281
|
+
|
282
|
+
# Passing one symbol as an argument of the methods: `#map`, `#then`, `#check`, `#accept`, `#reject`
|
283
|
+
Kind::Maybe['1'].map(:to_i) # #<Kind::Some value=1>
|
284
|
+
Kind::Maybe[' '].then(:strip) # #<Kind::Some value="">
|
285
|
+
|
286
|
+
Kind::Maybe['1'].map!(:to_i).accept(:odd?) # #<Kind::Some value=1>
|
287
|
+
Kind::Maybe[' '].then!(:strip).reject(:empty?) # #<Kind::None value=nil>
|
288
|
+
|
289
|
+
# `Kind::Maybe#on` making use of a block to handle Some or None results.
|
290
|
+
number = Kind::Maybe['2'].then(:to_i).reject(:even?).on do |result|
|
291
|
+
result.none { 0 }
|
292
|
+
result.some { 1 }
|
293
|
+
end
|
294
|
+
|
295
|
+
p number # 0
|
296
|
+
```
|
297
|
+
|
298
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Either` (either monad). This is basically the same as the `Maybe` monad, but with `Some` called `Right` and `None` called `Left`. But this time, `Left` is also allowed to have an underlying value. This module isn't loaded by default, so you will need to require it.
|
299
|
+
```ruby
|
300
|
+
require 'kind/either'
|
301
|
+
|
302
|
+
# Use the methods Kind::Left() or Kind::Right() to create either monads
|
303
|
+
Kind::Left(0) # #<Kind::Left value=0>
|
304
|
+
Kind::Right(1) # #<Kind::Right value=1>
|
305
|
+
|
306
|
+
# The Kind::Either.new() or Kind::Either[] also creates a Kind::Right monad
|
307
|
+
Kind::Either.new(2) # #<Kind::Right value=2>
|
308
|
+
Kind::Either[3] # #<Kind::Right value=3>
|
309
|
+
|
310
|
+
# An Either has methods that allow you to know what kind it is.
|
311
|
+
monad = Kind::Right(1)
|
312
|
+
monad.right? # true
|
313
|
+
monad.left? # false
|
314
|
+
|
315
|
+
# This monad allows you to chain a sequence of operations that will continue while the output
|
316
|
+
# of each step is a Right monad. So, if some step return a Left, all of the next steps will be avoided.
|
317
|
+
# Let's see an example of how you can use the method #map to define a sequence of operations.
|
318
|
+
|
319
|
+
def do_some_calculation(arg)
|
320
|
+
Kind::Right(arg)
|
321
|
+
.map { |value| Kind::Numeric?(value) ? Kind::Right(value + 2) : Kind::Left('value must be numeric') }
|
322
|
+
.map { |value| value.odd? ? Kind::Right(value) : Kind::Left('value can\'t be even') }
|
323
|
+
.map { |value| Kind::Right(value * 3) }
|
324
|
+
end
|
325
|
+
|
326
|
+
do_some_calculation('1') # #<Kind::Left value="value must be numeric">
|
327
|
+
do_some_calculation(2) # #<Kind::Left value="value can't be even">
|
328
|
+
do_some_calculation(1) # #<Kind::Right value=9>
|
329
|
+
|
330
|
+
# You can use procs/lambdas as an alternative of blocks
|
331
|
+
Add = ->(a, b) do
|
332
|
+
return Kind::Right(a + b) if Kind::Numeric?(a, b)
|
333
|
+
|
334
|
+
Kind::Left('the arguments must be numerics')
|
335
|
+
end
|
336
|
+
|
337
|
+
Double = ->(number) do
|
338
|
+
return Kind::Right(number * 2) if Kind::Numeric?(number)
|
339
|
+
|
340
|
+
Kind::Left('the argument must be numeric')
|
341
|
+
end
|
342
|
+
|
343
|
+
AsString = ->(value) { Kind::Right(value.to_s) }
|
344
|
+
|
345
|
+
Add.(1, 2).map(&Double).map(&Double) # #<Kind::Right value=12>
|
346
|
+
Add.(1, 2).map(&AsString).map(&Double) # #<Kind::Left value="the argument must be numeric">
|
347
|
+
|
348
|
+
# The method #then is an alias for #map
|
349
|
+
Add.(2, 2).then(&Double).then(&AsString) # #<Kind::Right value="8">
|
350
|
+
|
351
|
+
# An exception will occur when your block or lambda doesn't return a Kind::Either
|
352
|
+
Add.(2, 2).map { |number| number * 2 } # Kind::Monad::Error (8 expected to be a kind of Kind::Right | Kind::Left)
|
353
|
+
|
354
|
+
# The methods #map, #then auto handle StandardError exceptions,
|
355
|
+
# so Left will be returned when an exception occur.
|
356
|
+
Add.(0, 0).map { |number| Kind::Right(10 / number) } # #<Kind::Left value=#<ZeroDivisionError: divided by 0>>
|
357
|
+
|
358
|
+
# You can use #map! or #then! if you don't want this auto exception handling.
|
359
|
+
Add.(0, 0).map! { |number| Kind::Right(10 / number) } # ZeroDivisionError (divided by 0)
|
360
|
+
|
361
|
+
Add.(0, 0).then! { |number| Kind::Right(10 / number) } # ZeroDivisionError (divided by 0)
|
362
|
+
```
|
363
|
+
|
364
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Result` (an Either monad variation)
|
365
|
+
|
366
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Function`.
|
367
|
+
|
368
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Functional`.
|
369
|
+
|
370
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Try.presence` and improve the input/output handling of `Kind::Try.call`.
|
371
|
+
|
372
|
+
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Dig.presence` and improve the input/output handling of `Kind::Dig.call`.
|
373
|
+
|
374
|
+
* [#47](https://github.com/serradura/kind/pull/47) - Add `Kind.is!`
|
375
|
+
|
376
|
+
* [#47](https://github.com/serradura/kind/pull/47) - Create aliases to the methods `Kind.of` (`Kind.of!`) and `Kind.respond_to` (`Kind.respond_to!`)
|
377
|
+
|
378
|
+
* [#47](https://github.com/serradura/kind/pull/47) - Add `Kind[]` as the `Kind::Of()` substitute.
|
379
|
+
|
380
|
+
* [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Either::Methods` and `Kind::Result::Methods`
|
381
|
+
|
382
|
+
* [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Undefined.empty?`
|
383
|
+
|
384
|
+
* [#50](https://github.com/serradura/kind/pull/50) - Add `Kind::<Type>.empty_or` as an alias of `Kind::<Type>.value_or_empty`
|
385
|
+
|
386
|
+
* [#46](https://github.com/serradura/kind/pull/46), [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Functional::Action`.
|
387
|
+
|
388
|
+
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Action`.
|
389
|
+
|
390
|
+
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Maybe::ImmutableAttributes`.
|
391
|
+
|
392
|
+
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Maybe::Methods`.
|
393
|
+
|
394
|
+
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Enum`.
|
395
|
+
|
396
|
+
* [#51](https://github.com/serradura/kind/pull/51) - Modularize all the kind components. So now you can require only the modules/features that do you want, `kind/action` is the minimal requirement for all of them.
|
397
|
+
* `kind/action`
|
398
|
+
* `kind/dig`
|
399
|
+
* `kind/either`
|
400
|
+
* `kind/empty`
|
401
|
+
* `kind/enum`
|
402
|
+
* `kind/function`
|
403
|
+
* `kind/functional`
|
404
|
+
* `kind/functional/action`
|
405
|
+
* `kind/immutable_attributes`
|
406
|
+
* `kind/maybe`
|
407
|
+
* `kind/objects`
|
408
|
+
* `kind/presence`
|
409
|
+
* `kind/result`
|
410
|
+
* `kind/try`
|
411
|
+
* `kind/validator`
|
412
|
+
|
413
|
+
* [#52](https://github.com/serradura/kind/pull/52) - Improve `Kind::Validator`, now will be possible to make use of `lambdas` or objects that responds to `.===` and `.name` to perform a kind validation. e.g.
|
414
|
+
```ruby
|
415
|
+
class User
|
416
|
+
include ActiveModel::Validations
|
417
|
+
|
418
|
+
attr_reader :name, :bool
|
419
|
+
|
420
|
+
FilledString = ->(value) { value.kind_of?(String) && !value.empty? }
|
421
|
+
|
422
|
+
Bool = Object.new
|
423
|
+
def Bool.===(value)
|
424
|
+
value == true || value == false
|
425
|
+
end
|
426
|
+
def Bool.name; 'Bool'; end
|
427
|
+
|
428
|
+
validates :name, kind: FilledString
|
429
|
+
validates :bool, kind: Bool
|
430
|
+
|
431
|
+
def initialize(name:, bool:)
|
432
|
+
@name, @bool = name, bool
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
user = User.new(name: '', bool: 1)
|
437
|
+
|
438
|
+
user.valid? # true
|
439
|
+
user.errors[:name] # ['invalid kind']
|
440
|
+
user.errors[:bool] # ['must be a kind of Bool']
|
441
|
+
|
442
|
+
User.new(name: 'Serradura', bool: true).valid? # true
|
443
|
+
```
|
444
|
+
|
445
|
+
* [#52](https://github.com/serradura/kind/pull/52) - Add `Kind::Enum.===`.
|
446
|
+
|
447
|
+
### Deprecated
|
448
|
+
|
449
|
+
* [#47](https://github.com/serradura/kind/pull/47) - Deprecate `Kind.is` and `Kind::Of()`.
|
450
|
+
|
451
|
+
* [#48](https://github.com/serradura/kind/pull/48) - Deprecate `Kind::Maybe()` and `Kind::Optional()`
|
452
|
+
|
453
|
+
### Changes
|
454
|
+
|
455
|
+
* [#48](https://github.com/serradura/kind/pull/48) - Rename `Kind::TypeChecker` to `Kind::Object` and `Kind::TypeChecker::Object` to `Kind::Object::Instance`.
|
456
|
+
|
457
|
+
[⬆️ Back to Top](#changelog-)
|
458
|
+
|
459
|
+
5.1.0 (2021-02-23)
|
460
|
+
------------------
|
461
|
+
|
462
|
+
### Added
|
463
|
+
|
464
|
+
* [#45](https://github.com/serradura/kind/pull/45) - Add support to Ruby `>= 2.1.0`.
|
465
|
+
|
466
|
+
### Deprecated
|
467
|
+
|
468
|
+
* [#45](https://github.com/serradura/kind/pull/45) - `kind/active_model/validation` is deprecated; use `kind/validator` instead.
|
469
|
+
|
470
|
+
5.0.0 (2021-02-22)
|
471
|
+
------------------
|
472
|
+
|
473
|
+
### Breaking Changes
|
474
|
+
|
475
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Now, do you need to require `"kind/empty/constant"` to define the constant `Empty` as a `Kind::Empty` alias.
|
476
|
+
|
477
|
+
### Removed
|
478
|
+
|
479
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Is.call`
|
480
|
+
|
481
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Of.call`
|
482
|
+
|
483
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Types.add`.
|
484
|
+
|
485
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Of::<Type>` and `Kind::Is::<Type>` modules.
|
486
|
+
|
487
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Checker`, `Kind::Checker::Protocol`, `Kind::Checker::Factory`.
|
488
|
+
|
489
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.is` without arguments.
|
490
|
+
|
491
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` without arguments.
|
492
|
+
|
493
|
+
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` with a single argument (the kind).
|
494
|
+
|
495
|
+
4.1.0 (2021-02-22)
|
496
|
+
------------------
|
497
|
+
|
498
|
+
### Added
|
499
|
+
|
500
|
+
* [#43](https://github.com/serradura/kind/pull/43) - Make `Kind::Maybe::Typed` verify the kind of the value via `===`, because of this, now is possible to use type checkers in typed Maybes.
|
501
|
+
```ruby
|
502
|
+
Kind::Maybe(Kind::Boolean).wrap(nil).value_or(false) # false
|
503
|
+
|
504
|
+
Kind::Maybe(Kind::Boolean).wrap(true).value_or(false) # true
|
505
|
+
```
|
506
|
+
|
507
|
+
* [#43](https://github.com/serradura/kind/pull/43) - Add `Kind::<Type>.maybe` and `Kind::<Type>.optional`. This method returns a typed Maybe with the expected kind when it is invoked without arguments. But, if it receives arguments, it will behave like the `Kind::Maybe.wrap` method. e.g.
|
508
|
+
```ruby
|
509
|
+
Kind::Integer.maybe #<Kind::Maybe::Typed:0x0000... @kind=Kind::Integer>
|
510
|
+
|
511
|
+
Kind::Integer.maybe(0).some? # true
|
512
|
+
Kind::Integer.maybe { 1 }.some? # true
|
513
|
+
Kind::Integer.maybe(2) { |n| n * 2 }.some? # true
|
514
|
+
|
515
|
+
Kind::Integer.maybe { 2 / 0 }.none? # true
|
516
|
+
Kind::Integer.maybe(2) { |n| n / 0 }.none? # true
|
517
|
+
Kind::Integer.maybe('2') { |n| n * n }.none? # true
|
518
|
+
```
|
519
|
+
|
520
|
+
* [#43](https://github.com/serradura/kind/pull/43) - Make the `:respond_to` kind validation verify by one or multiple methods. e.g.
|
521
|
+
```ruby
|
522
|
+
validates :params, kind: { respond_to: [:[], :values_at] }
|
523
|
+
```
|
524
|
+
|
525
|
+
* [#43](https://github.com/serradura/kind/pull/43) - Make the `:of` kind validation verify the expected value kind using `===`, because of this, now is possible to use type checkers as expected kinds. e.g.
|
526
|
+
```ruby
|
527
|
+
validates :alive, kind: Kind::Boolean
|
528
|
+
```
|
529
|
+
|
72
530
|
4.0.0 (2021-02-22)
|
73
531
|
------------------
|
74
532
|
|