kind 5.1.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.tool-versions +1 -1
- data/.travis.sh +37 -10
- data/CHANGELOG.md +518 -29
- data/README.md +48 -45
- data/kind.gemspec +2 -2
- data/lib/kind.rb +2 -49
- 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 +1 -1
- data/lib/kind/basic.rb +83 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{core → basic}/undefined.rb +6 -1
- data/lib/kind/{core/dig.rb → 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/{core/empty.rb → empty.rb} +2 -0
- data/lib/kind/{core/empty → empty}/constant.rb +0 -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 +87 -0
- data/lib/kind/functional/steps.rb +22 -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 +69 -0
- 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 +50 -0
- data/lib/kind/maybe/some.rb +132 -0
- data/lib/kind/maybe/typed.rb +35 -0
- data/lib/kind/{core/maybe/wrappable.rb → maybe/wrapper.rb} +8 -4
- 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/{core/type_checkers/ruby → objects/modules/core}/array.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/class.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/comparable.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/enumerable.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/enumerator.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/file.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/float.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/hash.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/integer.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/io.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/method.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/module.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/numeric.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/proc.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/queue.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/range.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/regexp.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/string.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/struct.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/symbol.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/time.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{core/type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{core/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/{core/presence.rb → 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 +46 -0
- data/lib/kind/validator.rb +14 -10
- data/lib/kind/version.rb +1 -1
- metadata +91 -49
- data/lib/kind/core.rb +0 -15
- data/lib/kind/core/error.rb +0 -15
- data/lib/kind/core/maybe.rb +0 -42
- data/lib/kind/core/maybe/none.rb +0 -57
- data/lib/kind/core/maybe/result.rb +0 -51
- data/lib/kind/core/maybe/some.rb +0 -90
- data/lib/kind/core/maybe/typed.rb +0 -29
- data/lib/kind/core/try.rb +0 -34
- data/lib/kind/core/type_checker.rb +0 -87
- data/lib/kind/core/type_checkers.rb +0 -30
- data/lib/kind/core/utils/kind.rb +0 -61
- data/lib/kind/core/utils/undefined.rb +0 -7
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module OF
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def class?(value) # :nodoc:
|
8
|
+
value.kind_of?(::Class)
|
9
|
+
end
|
10
|
+
|
11
|
+
def module?(value) # :nodoc:
|
12
|
+
::Module == value || (value.kind_of?(::Module) && !class?(value))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private_constant :OF
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/__lib__/of'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
module STRICT
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def error(kind_name, value, label = nil) # :nodoc:
|
10
|
+
raise Error.new(kind_name, value, label: label)
|
11
|
+
end
|
12
|
+
|
13
|
+
def object_is_a(kind, value, label = nil) # :nodoc:
|
14
|
+
return value if kind === value
|
15
|
+
|
16
|
+
error(kind.name, value, label)
|
17
|
+
end
|
18
|
+
|
19
|
+
def kind_of(kind, value, kind_name = nil) # :nodoc:
|
20
|
+
return value if kind === value
|
21
|
+
|
22
|
+
error(kind_name || kind.name, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def module_or_class(value) # :nodoc:
|
26
|
+
kind_of(::Module, value, 'Module/Class')
|
27
|
+
end
|
28
|
+
|
29
|
+
def class!(value) # :nodoc:
|
30
|
+
kind_of(::Class, value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def module!(value) # :nodoc:
|
34
|
+
return value if OF.module?(value)
|
35
|
+
|
36
|
+
error('Module', value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def not_nil(value, label) # :nodoc:
|
40
|
+
return value unless value.nil?
|
41
|
+
|
42
|
+
label_text = label ? "#{label}: " : ''
|
43
|
+
|
44
|
+
raise Error.new("#{label_text}expected to not be nil")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private_constant :STRICT
|
49
|
+
end
|
data/lib/kind/action.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/empty'
|
5
|
+
require 'kind/result'
|
6
|
+
require 'kind/immutable_attributes'
|
7
|
+
require 'kind/__lib__/action_steps'
|
8
|
+
|
9
|
+
module Kind
|
10
|
+
module Action
|
11
|
+
CALL_TMPL = [
|
12
|
+
'def self.call(arg)',
|
13
|
+
' new(Kind.of!(::Hash, arg)).call',
|
14
|
+
'end',
|
15
|
+
'',
|
16
|
+
'def call',
|
17
|
+
' result = call!',
|
18
|
+
'',
|
19
|
+
' return result if Kind::Result::Monad === result',
|
20
|
+
'',
|
21
|
+
' raise Kind::Error, "#{self.class.name}#call! must return a Success() or Failure()"',
|
22
|
+
'end'
|
23
|
+
].join("\n").freeze
|
24
|
+
|
25
|
+
private_constant :CALL_TMPL
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
include ImmutableAttributes::ClassMethods
|
29
|
+
|
30
|
+
def to_proc
|
31
|
+
@to_proc ||= ->(arg) { call(arg) }
|
32
|
+
end
|
33
|
+
|
34
|
+
ATTRIBUTE_METHODS = [
|
35
|
+
:attributes, :attribute,
|
36
|
+
:attribute?, :attribute!,
|
37
|
+
:with_attribute, :with_attributes,
|
38
|
+
:nil_attributes, :nil_attributes?
|
39
|
+
]
|
40
|
+
|
41
|
+
private_constant :ATTRIBUTE_METHODS
|
42
|
+
|
43
|
+
def kind_action!
|
44
|
+
return self if respond_to?(:call)
|
45
|
+
|
46
|
+
public_methods = self.public_instance_methods - ::Object.new.methods
|
47
|
+
|
48
|
+
remaining_methods = public_methods - (__attributes__.keys + ATTRIBUTE_METHODS)
|
49
|
+
|
50
|
+
unless remaining_methods.include?(:call!)
|
51
|
+
raise Kind::Error.new("expected #{self} to implement `#call!`")
|
52
|
+
end
|
53
|
+
|
54
|
+
if remaining_methods.size > 1
|
55
|
+
raise Kind::Error.new("#{self} can only have `#call!` as its public method")
|
56
|
+
end
|
57
|
+
|
58
|
+
call_parameters = public_instance_method(:call!).parameters
|
59
|
+
|
60
|
+
unless call_parameters.empty?
|
61
|
+
raise ArgumentError, "#{self.name}#call! must receive no arguments"
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.inherited(_)
|
65
|
+
raise RuntimeError, "#{self.name} is a Kind::Action and it can't be inherited"
|
66
|
+
end
|
67
|
+
|
68
|
+
self.send(:private_class_method, :new)
|
69
|
+
|
70
|
+
self.class_eval(CALL_TMPL)
|
71
|
+
|
72
|
+
self.send(:alias_method, :[], :call)
|
73
|
+
self.send(:alias_method, :===, :call)
|
74
|
+
self.send(:alias_method, :yield, :call)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module StepAdapters
|
79
|
+
private
|
80
|
+
|
81
|
+
def Check!(mthod); __Check(mthod, Empty::HASH); end
|
82
|
+
def Step!(mthod); __Step(mthod, Empty::HASH); end
|
83
|
+
def Map!(mthod); __Map(mthod, Empty::HASH); end
|
84
|
+
def Tee!(_mthod); raise NotImplementedError; end
|
85
|
+
def Try!(mthod, opt = Empty::HASH); __Try(mthod, Empty::HASH, opt); end
|
86
|
+
|
87
|
+
def __resolve_step(method_name, value)
|
88
|
+
m = method(method_name)
|
89
|
+
m.arity > 0 ? m.call(value) : m.call
|
90
|
+
end
|
91
|
+
|
92
|
+
def __map_step_exception(value)
|
93
|
+
{ exception: value }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private_constant :StepAdapters
|
98
|
+
|
99
|
+
def self.included(base)
|
100
|
+
Kind.of_class(base).extend(ClassMethods)
|
101
|
+
|
102
|
+
base.send(:include, ACTION_STEPS)
|
103
|
+
base.send(:include, StepAdapters)
|
104
|
+
base.send(:include, ImmutableAttributes::Reader)
|
105
|
+
end
|
106
|
+
|
107
|
+
include ImmutableAttributes::Initializer
|
108
|
+
|
109
|
+
def inspect
|
110
|
+
'#<%s attributes=%p nil_attributes=%p>' % [self.class.name, attributes, nil_attributes]
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def Failure(arg1 = UNDEFINED, arg2 = UNDEFINED)
|
116
|
+
arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
|
117
|
+
|
118
|
+
Result::Failure[arg1, arg2, value_must_be_a: ::Hash]
|
119
|
+
end
|
120
|
+
|
121
|
+
def Success(arg1 = UNDEFINED, arg2 = UNDEFINED)
|
122
|
+
arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
|
123
|
+
|
124
|
+
Result::Success[arg1, arg2, value_must_be_a: ::Hash]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
warn '[DEPRECATION] "kind/active_model/validation" is deprecated; use "kind/validator" instead.' \
|
3
|
+
warn '[DEPRECATION] "kind/active_model/validation" is deprecated; use "kind/validator" instead. ' \
|
4
4
|
'It will be removed on next major release.'
|
5
5
|
|
6
6
|
require 'kind/validator'
|
data/lib/kind/basic.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/version'
|
4
|
+
|
5
|
+
require 'kind/__lib__/kind'
|
6
|
+
require 'kind/__lib__/undefined'
|
7
|
+
|
8
|
+
require 'kind/basic/undefined'
|
9
|
+
require 'kind/basic/error'
|
10
|
+
|
11
|
+
module Kind
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def is?(kind, arg)
|
15
|
+
KIND.is?(kind, arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def is(*args)
|
19
|
+
warn '[DEPRECATION] Kind.is will behave like Kind.is! in the next major release; ' \
|
20
|
+
'use Kind.is? instead.'
|
21
|
+
|
22
|
+
is?(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def is!(kind, arg, label: nil)
|
26
|
+
return arg if KIND.is?(kind, arg)
|
27
|
+
|
28
|
+
label_text = label ? "#{label}: " : ''
|
29
|
+
|
30
|
+
raise Kind::Error.new("#{label_text}#{arg} expected to be a #{kind}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def of?(kind, *args)
|
34
|
+
KIND.of?(kind, args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def of_class?(value)
|
38
|
+
OF.class?(value)
|
39
|
+
end
|
40
|
+
|
41
|
+
def of_module?(value)
|
42
|
+
OF.module?(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def respond_to?(value, *method_names)
|
46
|
+
return super(value) if method_names.empty?
|
47
|
+
|
48
|
+
KIND.interface?(method_names, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def of(kind, value, label: nil)
|
52
|
+
STRICT.object_is_a(kind, value, label)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :of!, :of
|
56
|
+
|
57
|
+
def of_class(value)
|
58
|
+
STRICT.class!(value)
|
59
|
+
end
|
60
|
+
|
61
|
+
def of_module(value)
|
62
|
+
STRICT.module!(value)
|
63
|
+
end
|
64
|
+
|
65
|
+
def of_module_or_class(value)
|
66
|
+
STRICT.module_or_class(value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def respond_to(value, *method_names)
|
70
|
+
method_names.each { |method_name| KIND.respond_to!(method_name, value) }
|
71
|
+
|
72
|
+
value
|
73
|
+
end
|
74
|
+
alias_method :respond_to!, :respond_to
|
75
|
+
|
76
|
+
def value(kind, value, default:)
|
77
|
+
KIND.value(kind, value, of(kind, default))
|
78
|
+
end
|
79
|
+
|
80
|
+
def or_nil(kind, value)
|
81
|
+
return value if kind === value
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Error < StandardError
|
5
|
+
INVALID_DEFAULT_ARG = 'the default value must be defined as an argument or block'.freeze
|
6
|
+
|
7
|
+
def self.wrong_number_of_args!(given:, expected:)
|
8
|
+
raise ArgumentError, "wrong number of arguments (given #{given}, expected #{expected})"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.invalid_default_arg!
|
12
|
+
raise ArgumentError, INVALID_DEFAULT_ARG
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(arg, object = UNDEFINED, label: nil)
|
16
|
+
if UNDEFINED == object
|
17
|
+
# Will be used when the exception was raised with a message. e.g:
|
18
|
+
# raise Kind::Error, "some message"
|
19
|
+
super(arg)
|
20
|
+
else
|
21
|
+
label_text = label ? "#{label}: " : ''
|
22
|
+
|
23
|
+
super("#{label_text}#{object.inspect} expected to be a kind of #{arg}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private_constant :INVALID_DEFAULT_ARG
|
28
|
+
end
|
29
|
+
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Kind
|
3
4
|
Undefined = Object.new.tap do |undefined|
|
4
5
|
def undefined.inspect
|
5
6
|
@inspect ||= 'Kind::Undefined'.freeze
|
6
7
|
end
|
8
|
+
undefined.inspect
|
9
|
+
|
10
|
+
def undefined.empty?
|
11
|
+
true
|
12
|
+
end
|
7
13
|
|
8
14
|
def undefined.to_s
|
9
15
|
inspect
|
@@ -23,7 +29,6 @@ module Kind
|
|
23
29
|
default.respond_to?(:call) ? default.call : default
|
24
30
|
end
|
25
31
|
|
26
|
-
undefined.inspect
|
27
32
|
undefined.freeze
|
28
33
|
end
|
29
34
|
end
|
@@ -1,23 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/empty'
|
5
|
+
require 'kind/presence'
|
6
|
+
|
3
7
|
module Kind
|
4
8
|
module Dig
|
5
9
|
extend self
|
6
10
|
|
7
|
-
def call(data, keys)
|
8
|
-
return unless keys.kind_of?(::Array)
|
9
|
-
|
11
|
+
def call!(data, keys = Empty::ARRAY) # :nodoc
|
10
12
|
keys.reduce(data) do |memo, key|
|
11
13
|
value = get(memo, key)
|
12
14
|
|
13
|
-
break if KIND.
|
15
|
+
break if KIND.nil_or_undefined?(value)
|
14
16
|
|
15
17
|
value
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
def call(data, *input)
|
22
|
+
args = input.size == 1 && input[0].kind_of?(::Array) ? input[0] : input
|
23
|
+
|
24
|
+
result = call!(data, args)
|
25
|
+
|
26
|
+
return result unless block_given?
|
27
|
+
|
28
|
+
yield(result) unless KIND.nil_or_undefined?(result)
|
29
|
+
end
|
30
|
+
|
31
|
+
def presence(*args, &block)
|
32
|
+
Presence.(call(*args, &block))
|
33
|
+
end
|
34
|
+
|
19
35
|
def [](*keys)
|
20
|
-
->(data) { call(data, keys) }
|
36
|
+
->(data) { call!(data, keys) }
|
21
37
|
end
|
22
38
|
|
23
39
|
private
|
data/lib/kind/either.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
module Either
|
7
|
+
require 'kind/either/monad'
|
8
|
+
require 'kind/either/left'
|
9
|
+
require 'kind/either/right'
|
10
|
+
require 'kind/either/methods'
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def new(value)
|
15
|
+
Right[value]
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :[], :new
|
19
|
+
|
20
|
+
def self.from
|
21
|
+
result = yield
|
22
|
+
|
23
|
+
Either::Monad === result ? result : Either::Right[result]
|
24
|
+
rescue StandardError => e
|
25
|
+
Either::Left[e]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
extend Either::Methods
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Either::Left < Either::Monad
|
5
|
+
def left?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_or(default = UNDEFINED, &block)
|
10
|
+
Error.invalid_default_arg! if UNDEFINED == default && !block
|
11
|
+
|
12
|
+
UNDEFINED != default ? default : block.call(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def map(&_)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :map!, :map
|
20
|
+
alias_method :then, :map
|
21
|
+
alias_method :then!, :map
|
22
|
+
alias_method :and_then, :map
|
23
|
+
alias_method :and_then!, :map
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
'#<%s value=%p>' % ['Kind::Left', value]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|