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 +4 -4
- data/.travis.yml +4 -1
- data/README.md +56 -2
- data/lib/kind.rb +7 -25
- data/lib/kind/checker.rb +3 -71
- data/lib/kind/checker/factory.rb +35 -0
- data/lib/kind/checker/protocol.rb +73 -0
- data/lib/kind/maybe.rb +26 -1
- data/lib/kind/types.rb +1 -1
- data/lib/kind/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a234e4c63dea23906a65da0718515bff19ac7934a3e919535596042cfd605bba
|
4
|
+
data.tar.gz: 5bcb0f1f669a0e87de070c5095cf8f769ddf97dde4b2169060fb21769ffbd623
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 232d87a65618b51c3ec8756ad9d08bce53a49d50368d4629c8e694050502dddf12cdecd878193e40e09c8fcc13139b1a35383eedaa36a1660f7cf71f7e4d9810
|
7
|
+
data.tar.gz: 4cef62a76d8981fa7409e0d598448b35b4bb01794084ad2ab264741cbf0a78e6b9142352369892e124f130750847078f90297e5d1eda955881ebea0f13e96ec7
|
data/.travis.yml
CHANGED
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.
|
data/lib/kind.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
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
|
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
|
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
|
253
|
+
extend Checker::Protocol
|
272
254
|
|
273
255
|
def self.__kind; Object; end
|
274
256
|
|
data/lib/kind/checker.rb
CHANGED
@@ -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
|
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
|
data/lib/kind/maybe.rb
CHANGED
@@ -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
|
data/lib/kind/types.rb
CHANGED
@@ -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
|
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)
|
data/lib/kind/version.rb
CHANGED
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.
|
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-
|
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
|