dry-monads 1.3.5 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +152 -80
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/dry-monads.gemspec +31 -30
- data/lib/dry/monads/all.rb +2 -3
- data/lib/dry/monads/constants.rb +0 -2
- data/lib/dry/monads/curry.rb +2 -2
- data/lib/dry/monads/do/all.rb +35 -18
- data/lib/dry/monads/do.rb +48 -20
- data/lib/dry/monads/errors.rb +8 -5
- data/lib/dry/monads/lazy.rb +13 -5
- data/lib/dry/monads/list.rb +27 -37
- data/lib/dry/monads/maybe.rb +85 -26
- data/lib/dry/monads/registry.rb +20 -20
- data/lib/dry/monads/result/fixed.rb +31 -24
- data/lib/dry/monads/result.rb +37 -19
- data/lib/dry/monads/right_biased.rb +38 -31
- data/lib/dry/monads/task.rb +25 -28
- data/lib/dry/monads/transformer.rb +2 -1
- data/lib/dry/monads/traverse.rb +5 -1
- data/lib/dry/monads/try.rb +45 -18
- data/lib/dry/monads/unit.rb +9 -3
- data/lib/dry/monads/validated.rb +18 -18
- data/lib/dry/monads/version.rb +1 -1
- data/lib/dry/monads.rb +25 -4
- data/lib/dry-monads.rb +1 -1
- data/lib/json/add/dry/monads/maybe.rb +5 -5
- metadata +22 -54
- data/.codeclimate.yml +0 -12
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
- data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -30
- data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
- data/.github/workflows/ci.yml +0 -52
- data/.github/workflows/docsite.yml +0 -34
- data/.github/workflows/sync_configs.yml +0 -56
- data/.gitignore +0 -10
- data/.rspec +0 -4
- data/.rubocop.yml +0 -101
- data/.yardopts +0 -4
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -19
- data/Gemfile.devtools +0 -14
- data/Rakefile +0 -8
- data/bin/.gitkeep +0 -0
- data/bin/console +0 -17
- data/bin/setup +0 -7
- data/docsite/source/case-equality.html.md +0 -42
- data/docsite/source/do-notation.html.md +0 -207
- data/docsite/source/getting-started.html.md +0 -142
- data/docsite/source/index.html.md +0 -179
- data/docsite/source/list.html.md +0 -87
- data/docsite/source/maybe.html.md +0 -146
- data/docsite/source/pattern-matching.html.md +0 -68
- data/docsite/source/result.html.md +0 -190
- data/docsite/source/task.html.md +0 -126
- data/docsite/source/tracing-failures.html.md +0 -32
- data/docsite/source/try.html.md +0 -76
- data/docsite/source/unit.html.md +0 -36
- data/docsite/source/validated.html.md +0 -88
- data/lib/dry/monads/either.rb +0 -66
- data/log/.gitkeep +0 -0
- data/project.yml +0 -2
data/lib/dry/monads/registry.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'concurrent/map'
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
# Common, idiomatic monads for Ruby
|
7
5
|
#
|
@@ -9,20 +7,20 @@ module Dry
|
|
9
7
|
module Monads
|
10
8
|
@registry = {}
|
11
9
|
@constructors = nil
|
12
|
-
@
|
13
|
-
do:
|
14
|
-
lazy:
|
15
|
-
list:
|
16
|
-
maybe:
|
17
|
-
task:
|
18
|
-
try:
|
19
|
-
validated:
|
10
|
+
@constants = {
|
11
|
+
do: "Do::All",
|
12
|
+
lazy: "Lazy",
|
13
|
+
list: "List",
|
14
|
+
maybe: "Maybe",
|
15
|
+
task: "Task",
|
16
|
+
try: "Try",
|
17
|
+
validated: "Validated",
|
20
18
|
result: [
|
21
|
-
|
22
|
-
|
19
|
+
"Result",
|
20
|
+
"Result::Fixed"
|
23
21
|
]
|
24
22
|
}.freeze
|
25
|
-
@mixins = Concurrent::Map.new
|
23
|
+
@mixins = ::Concurrent::Map.new
|
26
24
|
|
27
25
|
class << self
|
28
26
|
private
|
@@ -46,27 +44,29 @@ module Dry
|
|
46
44
|
|
47
45
|
# @private
|
48
46
|
def known_monads
|
49
|
-
@
|
47
|
+
@constants.keys
|
50
48
|
end
|
51
49
|
|
52
50
|
# @private
|
53
51
|
def load_monad(name)
|
54
|
-
|
55
|
-
raise ArgumentError, "#{name.inspect} is not a known monad"
|
52
|
+
constants = @constants.fetch(name) {
|
53
|
+
raise ::ArgumentError, "#{name.inspect} is not a known monad"
|
56
54
|
}
|
57
|
-
Array(
|
55
|
+
Array(constants).each do |const_name|
|
56
|
+
const_name.split("::").reduce(Monads) { |mod, const| mod.const_get(const) }
|
57
|
+
end
|
58
58
|
end
|
59
59
|
|
60
60
|
# @private
|
61
61
|
def constructors
|
62
|
-
@constructors ||= registry.values.
|
62
|
+
@constructors ||= registry.values.filter_map { |m|
|
63
63
|
m::Constructors if m.const_defined?(:Constructors)
|
64
|
-
}
|
64
|
+
}
|
65
65
|
end
|
66
66
|
|
67
67
|
# @private
|
68
68
|
def all_loaded?
|
69
|
-
registry.size
|
69
|
+
registry.size.eql?(@constants.size)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -1,37 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
require "dry/monads/constants"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Monads
|
7
|
+
class Result
|
8
|
+
# @see Monads#Result
|
9
|
+
# @private
|
10
|
+
class Fixed < ::Module
|
11
|
+
def self.[](error, **options)
|
12
|
+
new(error, **options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(error, **_options)
|
16
|
+
super()
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
@mod = ::Module.new do
|
19
|
+
define_method(:Failure) do |value|
|
20
|
+
if error === value
|
21
|
+
Failure.new(value, RightBiased::Left.trace_caller)
|
22
|
+
else
|
23
|
+
# per https://github.com/dry-rb/dry-monads/pull/142
|
24
|
+
raise InvalidFailureTypeError.new(value)
|
25
|
+
end
|
19
26
|
end
|
20
|
-
end
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
28
|
+
def Success(value = Undefined, &block)
|
29
|
+
v = Undefined.default(value, block || Unit)
|
30
|
+
Success.new(v)
|
31
|
+
end
|
25
32
|
end
|
26
33
|
end
|
27
|
-
end
|
28
34
|
|
29
|
-
|
35
|
+
private
|
30
36
|
|
31
|
-
|
32
|
-
|
37
|
+
def included(base)
|
38
|
+
super
|
33
39
|
|
34
|
-
|
40
|
+
base.include(@mod)
|
41
|
+
end
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
data/lib/dry/monads/result.rb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/equalizer'
|
4
|
-
|
5
|
-
require 'dry/monads/constants'
|
6
|
-
require 'dry/monads/right_biased'
|
7
|
-
require 'dry/monads/transformer'
|
8
|
-
require 'dry/monads/conversion_stubs'
|
9
|
-
require 'dry/monads/unit'
|
10
|
-
|
11
3
|
module Dry
|
12
4
|
module Monads
|
13
5
|
# Represents an operation which either succeeded or failed.
|
@@ -86,6 +78,7 @@ module Dry
|
|
86
78
|
|
87
79
|
# @param value [Object] a value of a successful operation
|
88
80
|
def initialize(value)
|
81
|
+
super()
|
89
82
|
@value = value
|
90
83
|
end
|
91
84
|
|
@@ -115,8 +108,8 @@ module Dry
|
|
115
108
|
#
|
116
109
|
# @param args [Array<Object>] arguments will be transparently passed through to #bind
|
117
110
|
# @return [Result::Success]
|
118
|
-
def fmap(
|
119
|
-
Success.new(bind(
|
111
|
+
def fmap(...)
|
112
|
+
Success.new(bind(...))
|
120
113
|
end
|
121
114
|
|
122
115
|
# Returns result of applying first function to the internal value.
|
@@ -134,7 +127,7 @@ module Dry
|
|
134
127
|
# @return [String]
|
135
128
|
def to_s
|
136
129
|
if Unit.equal?(@value)
|
137
|
-
|
130
|
+
"Success()"
|
138
131
|
else
|
139
132
|
"Success(#{@value.inspect})"
|
140
133
|
end
|
@@ -147,6 +140,13 @@ module Dry
|
|
147
140
|
def flip
|
148
141
|
Failure.new(@value, RightBiased::Left.trace_caller)
|
149
142
|
end
|
143
|
+
|
144
|
+
# Ignores values and returns self, see {Failure#alt_map}
|
145
|
+
#
|
146
|
+
# @return [Result::Success]
|
147
|
+
def alt_map(_ = nil)
|
148
|
+
self
|
149
|
+
end
|
150
150
|
end
|
151
151
|
|
152
152
|
# Represents a value of a failed operation.
|
@@ -156,7 +156,7 @@ module Dry
|
|
156
156
|
include RightBiased::Left
|
157
157
|
include Dry::Equalizer(:failure)
|
158
158
|
|
159
|
-
singleton_class.
|
159
|
+
singleton_class.alias_method(:call, :new)
|
160
160
|
|
161
161
|
# Shortcut for Failure([...])
|
162
162
|
#
|
@@ -188,6 +188,7 @@ module Dry
|
|
188
188
|
# @param value [Object] failure value
|
189
189
|
# @param trace [String] caller line
|
190
190
|
def initialize(value, trace = RightBiased::Left.trace_caller)
|
191
|
+
super()
|
191
192
|
@value = value
|
192
193
|
@trace = trace
|
193
194
|
end
|
@@ -218,7 +219,8 @@ module Dry
|
|
218
219
|
# otherwise simply returns the first argument.
|
219
220
|
#
|
220
221
|
# @example
|
221
|
-
# Dry::Monads.Failure(ArgumentError.new('error message')).or(&:message)
|
222
|
+
# Dry::Monads.Failure(ArgumentError.new('error message')).or(&:message)
|
223
|
+
# # => "error message"
|
222
224
|
#
|
223
225
|
# @param args [Array<Object>] arguments that will be passed to a block
|
224
226
|
# if one was given, otherwise the first
|
@@ -232,7 +234,8 @@ module Dry
|
|
232
234
|
end
|
233
235
|
end
|
234
236
|
|
235
|
-
# A lifted version of `#or`. Wraps the passed value or the block
|
237
|
+
# A lifted version of `#or`. Wraps the passed value or the block
|
238
|
+
# result with Result::Success.
|
236
239
|
#
|
237
240
|
# @example
|
238
241
|
# Dry::Monads.Failure.new('no value').or_fmap('value') # => Success("value")
|
@@ -240,14 +243,14 @@ module Dry
|
|
240
243
|
#
|
241
244
|
# @param args [Array<Object>] arguments will be passed to the underlying `#or` call
|
242
245
|
# @return [Result::Success] Wrapped value
|
243
|
-
def or_fmap(
|
244
|
-
Success.new(self.or(
|
246
|
+
def or_fmap(...)
|
247
|
+
Success.new(self.or(...))
|
245
248
|
end
|
246
249
|
|
247
250
|
# @return [String]
|
248
251
|
def to_s
|
249
252
|
if Unit.equal?(@value)
|
250
|
-
|
253
|
+
"Failure()"
|
251
254
|
else
|
252
255
|
"Failure(#{@value.inspect})"
|
253
256
|
end
|
@@ -287,6 +290,21 @@ module Dry
|
|
287
290
|
def either(_, g)
|
288
291
|
g.(failure)
|
289
292
|
end
|
293
|
+
|
294
|
+
# Lifts a block/proc over Failure
|
295
|
+
#
|
296
|
+
# @overload alt_map(proc)
|
297
|
+
# @param proc [#call]
|
298
|
+
# @return [Result::Failure]
|
299
|
+
#
|
300
|
+
# @overload alt_map
|
301
|
+
# @param block [Proc]
|
302
|
+
# @return [Result::Failure]
|
303
|
+
#
|
304
|
+
def alt_map(proc = Undefined, &block)
|
305
|
+
f = Undefined.default(proc, block)
|
306
|
+
self.class.new(f.(failure), RightBiased::Left.trace_caller)
|
307
|
+
end
|
290
308
|
end
|
291
309
|
|
292
310
|
# A module that can be included for easier access to Result monads.
|
@@ -448,7 +466,7 @@ module Dry
|
|
448
466
|
end
|
449
467
|
|
450
468
|
class Invalid < Validated
|
451
|
-
#
|
469
|
+
# Converts to Result::Failure
|
452
470
|
#
|
453
471
|
# @return [Result::Failure]
|
454
472
|
def to_result
|
@@ -457,7 +475,7 @@ module Dry
|
|
457
475
|
end
|
458
476
|
end
|
459
477
|
|
460
|
-
require
|
478
|
+
require "dry/monads/registry"
|
461
479
|
register_mixin(:result, Result::Mixin)
|
462
480
|
end
|
463
481
|
end
|
@@ -1,10 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/monads/constants'
|
4
|
-
require 'dry/monads/unit'
|
5
|
-
require 'dry/monads/curry'
|
6
|
-
require 'dry/monads/errors'
|
7
|
-
|
8
3
|
module Dry
|
9
4
|
module Monads
|
10
5
|
# A common module for right-biased monads, such as Result/Either, Maybe, and Try.
|
@@ -20,7 +15,7 @@ module Dry
|
|
20
15
|
def m.to_proc
|
21
16
|
@to_proc ||= method(:new).to_proc
|
22
17
|
end
|
23
|
-
m.singleton_class.
|
18
|
+
m.singleton_class.alias_method(:call, :new)
|
24
19
|
end
|
25
20
|
|
26
21
|
# Unwraps the underlying value
|
@@ -70,8 +65,8 @@ module Dry
|
|
70
65
|
#
|
71
66
|
# @param [Array<Object>] args arguments will be transparently passed through to #bind
|
72
67
|
# @return [RightBiased::Right]
|
73
|
-
def tee(
|
74
|
-
bind(
|
68
|
+
def tee(...)
|
69
|
+
bind(...).bind { self }
|
75
70
|
end
|
76
71
|
|
77
72
|
# Abstract method for lifting a block over the monad type.
|
@@ -90,6 +85,16 @@ module Dry
|
|
90
85
|
self
|
91
86
|
end
|
92
87
|
|
88
|
+
# Ignores arguments and returns self. It exists to keep the interface
|
89
|
+
# identical to that of {RightBiased::Left}.
|
90
|
+
#
|
91
|
+
# @param _alt [RightBiased::Right, RightBiased::Left]
|
92
|
+
#
|
93
|
+
# @return [RightBiased::Right]
|
94
|
+
def |(_alt)
|
95
|
+
self
|
96
|
+
end
|
97
|
+
|
93
98
|
# A lifted version of `#or`. For {RightBiased::Right} acts in the same way as `#or`,
|
94
99
|
# that is returns itselt.
|
95
100
|
#
|
@@ -118,18 +123,18 @@ module Dry
|
|
118
123
|
# create_user.apply(name) # => Failure(:name_missing)
|
119
124
|
#
|
120
125
|
# @return [RightBiased::Left,RightBiased::Right]
|
121
|
-
def apply(val = Undefined)
|
126
|
+
def apply(val = Undefined, &block)
|
122
127
|
unless @value.respond_to?(:call)
|
123
128
|
raise TypeError, "Cannot apply #{val.inspect} to #{@value.inspect}"
|
124
129
|
end
|
125
130
|
|
126
|
-
Undefined.default(val)
|
131
|
+
Undefined.default(val, &block).fmap { curry.(_1) }
|
127
132
|
end
|
128
133
|
|
129
134
|
# @param other [Object]
|
130
135
|
# @return [Boolean]
|
131
136
|
def ===(other)
|
132
|
-
self.class
|
137
|
+
other.instance_of?(self.class) && value! === other.value!
|
133
138
|
end
|
134
139
|
|
135
140
|
# Maps the value to Dry::Monads::Unit, useful when you don't care
|
@@ -197,11 +202,11 @@ module Dry
|
|
197
202
|
# @api private
|
198
203
|
def deconstruct
|
199
204
|
if Unit.equal?(@value)
|
200
|
-
|
201
|
-
elsif
|
202
|
-
@value
|
203
|
-
else
|
205
|
+
EMPTY_ARRAY
|
206
|
+
elsif !@value.is_a?(::Array)
|
204
207
|
[@value]
|
208
|
+
else
|
209
|
+
@value
|
205
210
|
end
|
206
211
|
end
|
207
212
|
|
@@ -226,19 +231,12 @@ module Dry
|
|
226
231
|
|
227
232
|
private
|
228
233
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
[[value], EMPTY_HASH]
|
236
|
-
end
|
237
|
-
end
|
238
|
-
else
|
239
|
-
# @api private
|
240
|
-
def destructure(*args, **kwargs)
|
241
|
-
[args, kwargs]
|
234
|
+
# @api private
|
235
|
+
def destructure(value)
|
236
|
+
if value.is_a?(::Hash)
|
237
|
+
[EMPTY_ARRAY, value]
|
238
|
+
else
|
239
|
+
[[value], EMPTY_HASH]
|
242
240
|
end
|
243
241
|
end
|
244
242
|
|
@@ -255,7 +253,7 @@ module Dry
|
|
255
253
|
# @private
|
256
254
|
# @return [String] Caller location
|
257
255
|
def self.trace_caller
|
258
|
-
caller_locations(2,
|
256
|
+
caller_locations(2, 1)[0].to_s
|
259
257
|
end
|
260
258
|
|
261
259
|
# Raises an error on accessing internal value
|
@@ -299,11 +297,20 @@ module Dry
|
|
299
297
|
raise NotImplementedError
|
300
298
|
end
|
301
299
|
|
300
|
+
# Returns the passed value. Works in pair with {RightBiased::Right#|}.
|
301
|
+
#
|
302
|
+
# @param alt [RightBiased::Right, RightBiased::Left]
|
303
|
+
#
|
304
|
+
# @return [RightBiased::Right, RightBiased::Left]
|
305
|
+
def |(alt)
|
306
|
+
self.or(alt)
|
307
|
+
end
|
308
|
+
|
302
309
|
# A lifted version of `#or`. This is basically `#or` + `#fmap`.
|
303
310
|
#
|
304
311
|
# @example
|
305
|
-
# Dry::Monads.None.
|
306
|
-
# Dry::Monads.None.
|
312
|
+
# Dry::Monads.None.or_fmap('no value') # => Some("no value")
|
313
|
+
# Dry::Monads.None.or_fmap { Time.now } # => Some(current time)
|
307
314
|
#
|
308
315
|
# @return [RightBiased::Left, RightBiased::Right]
|
309
316
|
def or_fmap(*)
|
data/lib/dry/monads/task.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require 'dry/monads/unit'
|
6
|
-
require 'dry/monads/curry'
|
7
|
-
require 'dry/monads/conversion_stubs'
|
3
|
+
require "concurrent/promise"
|
8
4
|
|
9
5
|
module Dry
|
10
6
|
module Monads
|
@@ -15,7 +11,7 @@ module Dry
|
|
15
11
|
# @api public
|
16
12
|
class Task
|
17
13
|
# @api private
|
18
|
-
class Promise < Concurrent::Promise
|
14
|
+
class Promise < ::Concurrent::Promise
|
19
15
|
public :on_fulfill, :on_reject
|
20
16
|
end
|
21
17
|
private_constant :Promise
|
@@ -48,9 +44,11 @@ module Dry
|
|
48
44
|
# @example using a predefined executor
|
49
45
|
# Task[:fast] { do_quick_task }
|
50
46
|
#
|
51
|
-
# @param executor [Concurrent::AbstractExecutorService,Symbol]
|
52
|
-
#
|
53
|
-
#
|
47
|
+
# @param executor [Concurrent::AbstractExecutorService,Symbol]
|
48
|
+
# Either an executor instance
|
49
|
+
# or a name of predefined global
|
50
|
+
# from concurrent-ruby
|
51
|
+
#
|
54
52
|
# @return [Task]
|
55
53
|
def [](executor, &block)
|
56
54
|
new(Promise.execute(executor: executor, &block))
|
@@ -81,6 +79,7 @@ module Dry
|
|
81
79
|
end
|
82
80
|
|
83
81
|
include ConversionStubs[:to_maybe, :to_result]
|
82
|
+
extend ::Dry::Core::Deprecations[:"dry-monads"]
|
84
83
|
|
85
84
|
# @api private
|
86
85
|
attr_reader :promise
|
@@ -122,23 +121,23 @@ module Dry
|
|
122
121
|
# and returns another task
|
123
122
|
# @return [Task]
|
124
123
|
def bind(&block)
|
125
|
-
self.class.new(promise.flat_map {
|
124
|
+
self.class.new(promise.flat_map { block.(_1).promise })
|
126
125
|
end
|
127
|
-
|
126
|
+
deprecate :then, :bind
|
128
127
|
|
129
128
|
# @return [String]
|
130
129
|
def to_s
|
131
130
|
state = case promise.state
|
132
131
|
when :fulfilled
|
133
132
|
if Unit.equal?(value!)
|
134
|
-
|
133
|
+
"value=()"
|
135
134
|
else
|
136
135
|
"value=#{value!.inspect}"
|
137
136
|
end
|
138
137
|
when :rejected
|
139
138
|
"error=#{promise.reason.inspect}"
|
140
139
|
else
|
141
|
-
|
140
|
+
"?"
|
142
141
|
end
|
143
142
|
|
144
143
|
"Task(#{state})"
|
@@ -164,16 +163,14 @@ module Dry
|
|
164
163
|
)
|
165
164
|
|
166
165
|
promise.on_error do |v|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
child.on_reject(e)
|
174
|
-
end
|
166
|
+
inner = block.(v).promise
|
167
|
+
inner.execute
|
168
|
+
inner.on_success { child.on_fulfill(_1) }
|
169
|
+
inner.on_error { child.on_reject(_1) }
|
170
|
+
rescue StandardError => e
|
171
|
+
child.on_reject(e)
|
175
172
|
end
|
176
|
-
promise.on_success {
|
173
|
+
promise.on_success { child.on_fulfill(_1) }
|
177
174
|
|
178
175
|
self.class.new(child)
|
179
176
|
end
|
@@ -236,9 +233,9 @@ module Dry
|
|
236
233
|
#
|
237
234
|
# @param val [Task]
|
238
235
|
# @return [Task]
|
239
|
-
def apply(val = Undefined)
|
240
|
-
arg = Undefined.default(val)
|
241
|
-
bind { |f| arg.fmap {
|
236
|
+
def apply(val = Undefined, &block)
|
237
|
+
arg = Undefined.default(val, &block)
|
238
|
+
bind { |f| arg.fmap { curry(f).(_1) } }
|
242
239
|
end
|
243
240
|
|
244
241
|
# Maps a successful result to Unit, effectively discards it
|
@@ -267,8 +264,8 @@ module Dry
|
|
267
264
|
# @api private
|
268
265
|
def compare_promises(x, y)
|
269
266
|
x.equal?(y) ||
|
270
|
-
x.fulfilled? && y.fulfilled? && x.value == y.value ||
|
271
|
-
x.rejected? && y.rejected? && x.reason == y.reason
|
267
|
+
(x.fulfilled? && y.fulfilled? && x.value == y.value) ||
|
268
|
+
(x.rejected? && y.rejected? && x.reason == y.reason)
|
272
269
|
end
|
273
270
|
|
274
271
|
# Task constructors.
|
@@ -314,7 +311,7 @@ module Dry
|
|
314
311
|
end
|
315
312
|
end
|
316
313
|
|
317
|
-
require
|
314
|
+
require "dry/monads/registry"
|
318
315
|
register_mixin(:task, Task::Mixin)
|
319
316
|
end
|
320
317
|
end
|
@@ -27,7 +27,8 @@ module Dry
|
|
27
27
|
# Lifts a block/proc over the 3-level nested structure.
|
28
28
|
#
|
29
29
|
# @example
|
30
|
-
# List[Right(Some(1)), Left(Some(1))].fmap3 { |x| x + 1 }
|
30
|
+
# List[Right(Some(1)), Left(Some(1))].fmap3 { |x| x + 1 }
|
31
|
+
# # => List[Right(Some(2)), Left(Some(1))]
|
31
32
|
# Right(None).fmap3 { |x| x + 1 } # => Right(None)
|
32
33
|
#
|
33
34
|
# @param args [Array<Object>] arguments will be passed to the block or the proc
|
data/lib/dry/monads/traverse.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
# rubocop:disable Naming/ConstantName
|
4
|
+
# rubocop:disable Style/MutableConstant
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Monads
|
@@ -20,3 +21,6 @@ module Dry
|
|
20
21
|
Traverse.freeze
|
21
22
|
end
|
22
23
|
end
|
24
|
+
|
25
|
+
# rubocop:enable Style/MutableConstant
|
26
|
+
# rubocop:enable Naming/ConstantName
|