dry-monads 1.4.0 → 1.6.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 +21 -0
- data/LICENSE +1 -1
- data/README.md +4 -4
- data/dry-monads.gemspec +4 -4
- data/lib/dry/monads/all.rb +1 -2
- data/lib/dry/monads/constants.rb +0 -2
- data/lib/dry/monads/curry.rb +2 -2
- data/lib/dry/monads/do/all.rb +1 -3
- data/lib/dry/monads/do.rb +8 -14
- data/lib/dry/monads/errors.rb +3 -3
- data/lib/dry/monads/lazy.rb +0 -3
- data/lib/dry/monads/list.rb +7 -17
- data/lib/dry/monads/maybe.rb +8 -17
- data/lib/dry/monads/registry.rb +20 -20
- data/lib/dry/monads/result/fixed.rb +0 -2
- data/lib/dry/monads/result.rb +5 -13
- data/lib/dry/monads/right_biased.rb +11 -23
- data/lib/dry/monads/task.rb +10 -13
- data/lib/dry/monads/traverse.rb +0 -2
- data/lib/dry/monads/try.rb +5 -11
- data/lib/dry/monads/unit.rb +3 -1
- data/lib/dry/monads/validated.rb +1 -5
- data/lib/dry/monads/version.rb +1 -1
- data/lib/dry/monads.rb +24 -3
- data/lib/json/add/dry/monads/maybe.rb +2 -2
- metadata +25 -20
- data/lib/dry/monads/either.rb +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ccc6809b903aa20a600330e62b86d8164da8394f2b7c63740d6708c73386578
|
4
|
+
data.tar.gz: a1c92edd9908da609bfe9048bf5ca1220d1f7e4c2cc894df9ea025e7df578625
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9286042f25cbb89f74d7159ef238cb834f7dddc74890c7d575978a14bd69d8d95aa46728c0f7dbfa81507af068cba4f3efa871eed9ec60d95da62db6f9810320
|
7
|
+
data.tar.gz: d723b367ba2014fa7bf907316dd93cff45be330329c83281a8640aaaa480a83c20e222d8d89736caf6acc6675c61927e3e54bf0ecb1b4df73ec1d5e2999f0d9a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
2
|
|
3
|
+
## 1.6.0 2022-11-04
|
4
|
+
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
|
8
|
+
- This version uses dry-core 1.0 (@flash-gordon)
|
9
|
+
|
10
|
+
[Compare v1.5.0...v1.6.0](https://github.com/dry-rb/dry-monads/compare/v1.5.0...v1.6.0)
|
11
|
+
|
12
|
+
## 1.5.0 2022-10-16
|
13
|
+
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
|
17
|
+
- Use zeitwerk for auto-loading dry-monads classes (@flash-gordon)
|
18
|
+
- `Task#then` is deprecated in favor of `Task#bind` (@flash-gordon)
|
19
|
+
- Minimal Ruby version is now 2.7 (@flash-gordon)
|
20
|
+
- Either (old name of Result) was removed (@flash-gordon)
|
21
|
+
|
22
|
+
[Compare v1.4.0...v1.5.0](https://github.com/dry-rb/dry-monads/compare/v1.4.0...v1.5.0)
|
23
|
+
|
3
24
|
## 1.4.0 2021-07-20
|
4
25
|
|
5
26
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -8,10 +8,10 @@
|
|
8
8
|
# dry-monads [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
|
9
9
|
|
10
10
|
[![Gem Version](https://badge.fury.io/rb/dry-monads.svg)][gem]
|
11
|
-
[![CI Status](https://github.com/dry-rb/dry-monads/workflows/
|
11
|
+
[![CI Status](https://github.com/dry-rb/dry-monads/workflows/ci/badge.svg)][actions]
|
12
12
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f2eed41bf7f04b38b0a7691c2cf6e73c)][codacy]
|
13
13
|
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/f2eed41bf7f04b38b0a7691c2cf6e73c)][codacy]
|
14
|
-
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-monads.svg?branch=
|
14
|
+
[![Inline docs](http://inch-ci.org/github/dry-rb/dry-monads.svg?branch=main)][inchpages]
|
15
15
|
|
16
16
|
## Links
|
17
17
|
|
@@ -22,8 +22,8 @@
|
|
22
22
|
|
23
23
|
This library officially supports the following Ruby versions:
|
24
24
|
|
25
|
-
* MRI `>= 2.
|
26
|
-
*
|
25
|
+
* MRI `>= 2.7.0`
|
26
|
+
* jruby `>= 9.3` (postponed until 2.7 is supported)
|
27
27
|
|
28
28
|
## License
|
29
29
|
|
data/dry-monads.gemspec
CHANGED
@@ -22,18 +22,18 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
24
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
25
|
-
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-monads/blob/
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-monads/blob/main/CHANGELOG.md"
|
26
26
|
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-monads"
|
27
27
|
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-monads/issues"
|
28
28
|
|
29
|
-
spec.required_ruby_version = ">= 2.
|
29
|
+
spec.required_ruby_version = ">= 2.7.0"
|
30
30
|
|
31
31
|
# to update dependencies edit project.yml
|
32
32
|
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
33
|
-
spec.add_runtime_dependency "dry-core", "~> 0
|
33
|
+
spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
|
34
|
+
spec.add_runtime_dependency "zeitwerk", "~> 2.6"
|
34
35
|
|
35
36
|
spec.add_development_dependency "bundler"
|
36
|
-
spec.add_development_dependency "dry-types", ">= 0.1.2"
|
37
37
|
spec.add_development_dependency "rake"
|
38
38
|
spec.add_development_dependency "rspec"
|
39
39
|
end
|
data/lib/dry/monads/all.rb
CHANGED
data/lib/dry/monads/constants.rb
CHANGED
data/lib/dry/monads/curry.rb
CHANGED
@@ -7,8 +7,8 @@ module Dry
|
|
7
7
|
# @private
|
8
8
|
def self.call(value)
|
9
9
|
func = value.is_a?(Proc) ? value : value.method(:call)
|
10
|
-
seq_args = func.parameters.count { |type, _| type
|
11
|
-
seq_args += 1 if func.parameters.any? { |type, _| type
|
10
|
+
seq_args = func.parameters.count { |type, _| type.eql?(:req) || type.eql?(:opt) }
|
11
|
+
seq_args += 1 if func.parameters.any? { |type, _| type.eql?(:keyreq) }
|
12
12
|
|
13
13
|
if seq_args > 1
|
14
14
|
func.curry
|
data/lib/dry/monads/do/all.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/monads/do"
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
module Monads
|
7
5
|
module Do
|
@@ -104,7 +102,7 @@ module Dry
|
|
104
102
|
def included(base)
|
105
103
|
super
|
106
104
|
|
107
|
-
wrappers = ::Hash.new {
|
105
|
+
wrappers = ::Hash.new { _1[_2] = ::Module.new }
|
108
106
|
tracker = MethodTracker.new(wrappers)
|
109
107
|
base.extend(tracker)
|
110
108
|
base.extend(InstanceMixin) unless base.is_a?(::Class)
|
data/lib/dry/monads/do.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/monads/list"
|
4
|
-
require "dry/monads/do/mixin"
|
5
|
-
require "dry/monads/constants"
|
6
|
-
|
7
3
|
module Dry
|
8
4
|
module Monads
|
9
5
|
# An implementation of do-notation.
|
@@ -12,8 +8,6 @@ module Dry
|
|
12
8
|
module Do
|
13
9
|
extend Mixin
|
14
10
|
|
15
|
-
DELEGATE = ::RUBY_VERSION < "2.7" ? "*" : "..."
|
16
|
-
|
17
11
|
VISIBILITY_WORD = {
|
18
12
|
public: "",
|
19
13
|
private: "private ",
|
@@ -110,7 +104,7 @@ module Dry
|
|
110
104
|
# @return [Module]
|
111
105
|
def for(*methods)
|
112
106
|
::Module.new do
|
113
|
-
singleton_class.
|
107
|
+
singleton_class.define_method(:included) do |base|
|
114
108
|
mod = ::Module.new
|
115
109
|
base.prepend(mod)
|
116
110
|
base.extend(MethodTracker.new(methods, base, mod))
|
@@ -130,13 +124,13 @@ module Dry
|
|
130
124
|
# @api private
|
131
125
|
def wrap_method(target, method, visibility)
|
132
126
|
target.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
133
|
-
#{VISIBILITY_WORD[visibility]} def #{method}(
|
134
|
-
if block_given?
|
135
|
-
super
|
136
|
-
else
|
137
|
-
Do.() { super { |*ms| Do.bind(ms) } }
|
138
|
-
end
|
139
|
-
end
|
127
|
+
#{VISIBILITY_WORD[visibility]} def #{method}(...) # private def create_acccount(...)
|
128
|
+
if block_given? # if block_given?
|
129
|
+
super # super
|
130
|
+
else # else
|
131
|
+
Do.() { super { |*ms| Do.bind(ms) } } # Do.() { super { |*ms| Do.bind(ms) } }
|
132
|
+
end # end
|
133
|
+
end # end
|
140
134
|
RUBY
|
141
135
|
end
|
142
136
|
|
data/lib/dry/monads/errors.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Dry
|
4
4
|
module Monads
|
5
5
|
# An unsuccessful result of extracting a value from a monad.
|
6
|
-
class UnwrapError < StandardError
|
6
|
+
class UnwrapError < ::StandardError
|
7
7
|
attr_reader :receiver
|
8
8
|
|
9
9
|
def initialize(receiver)
|
@@ -13,14 +13,14 @@ module Dry
|
|
13
13
|
end
|
14
14
|
|
15
15
|
# An error thrown on returning a Failure of unknown type.
|
16
|
-
class InvalidFailureTypeError < StandardError
|
16
|
+
class InvalidFailureTypeError < ::StandardError
|
17
17
|
def initialize(failure)
|
18
18
|
super("Cannot create Failure from #{failure.inspect}, it doesn't meet the constraints")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
# Improper use of None
|
23
|
-
class ConstructorNotAppliedError < NoMethodError
|
23
|
+
class ConstructorNotAppliedError < ::NoMethodError
|
24
24
|
def initialize(method_name, constructor_name)
|
25
25
|
super(
|
26
26
|
"For calling .#{method_name} on #{constructor_name}() build a value "\
|
data/lib/dry/monads/lazy.rb
CHANGED
data/lib/dry/monads/list.rb
CHANGED
@@ -1,15 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/equalizer"
|
4
|
-
|
5
|
-
require "dry/monads/maybe"
|
6
|
-
require "dry/monads/task"
|
7
|
-
require "dry/monads/result"
|
8
|
-
require "dry/monads/try"
|
9
|
-
require "dry/monads/validated"
|
10
|
-
require "dry/monads/transformer"
|
11
|
-
require "dry/monads/curry"
|
12
|
-
|
13
3
|
module Dry
|
14
4
|
module Monads
|
15
5
|
# The List monad.
|
@@ -110,10 +100,10 @@ module Dry
|
|
110
100
|
# @return [List]
|
111
101
|
def bind(*args)
|
112
102
|
if block_given?
|
113
|
-
List.coerce(value.map {
|
103
|
+
List.coerce(value.map { yield(_1, *args) }.reduce([], &:+))
|
114
104
|
else
|
115
105
|
obj, *rest = args
|
116
|
-
List.coerce(value.map {
|
106
|
+
List.coerce(value.map { obj.(_1, *rest) }.reduce([], &:+))
|
117
107
|
end
|
118
108
|
end
|
119
109
|
|
@@ -128,10 +118,10 @@ module Dry
|
|
128
118
|
# @return [List]
|
129
119
|
def fmap(*args)
|
130
120
|
if block_given?
|
131
|
-
List.new(value.map {
|
121
|
+
List.new(value.map { yield(_1, *args) })
|
132
122
|
else
|
133
123
|
obj, *rest = args
|
134
|
-
List.new(value.map {
|
124
|
+
List.new(value.map { obj.(_1, *rest) })
|
135
125
|
end
|
136
126
|
end
|
137
127
|
|
@@ -270,7 +260,7 @@ module Dry
|
|
270
260
|
self.class.warn(
|
271
261
|
"Automatic monad inference is deprecated, pass a type explicitly "\
|
272
262
|
"or use a predefined constant, e.g. List::Result\n"\
|
273
|
-
"#{caller.find {
|
263
|
+
"#{caller.find { _1 !~ %r{(lib/dry/monads)|(gems)} }}"
|
274
264
|
)
|
275
265
|
self.class.new(value, value[0].monad)
|
276
266
|
end
|
@@ -317,7 +307,7 @@ module Dry
|
|
317
307
|
# @return [List]
|
318
308
|
def apply(list = Undefined, &block)
|
319
309
|
v = Undefined.default(list, &block)
|
320
|
-
fmap(Curry).bind { |f| v.fmap {
|
310
|
+
fmap(Curry).bind { |f| v.fmap { f.(_1) } }
|
321
311
|
end
|
322
312
|
|
323
313
|
# Returns the List monad.
|
@@ -362,7 +352,7 @@ module Dry
|
|
362
352
|
List.new(collected)
|
363
353
|
else
|
364
354
|
Enumerator.new do |g|
|
365
|
-
value.each {
|
355
|
+
value.each { g << _1.value! if _1.some? }
|
366
356
|
end
|
367
357
|
end
|
368
358
|
end
|
data/lib/dry/monads/maybe.rb
CHANGED
@@ -1,14 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/equalizer"
|
4
|
-
require "dry/core/deprecations"
|
5
|
-
require "dry/core/class_attributes"
|
6
|
-
|
7
|
-
require "dry/monads/right_biased"
|
8
|
-
require "dry/monads/transformer"
|
9
|
-
require "dry/monads/unit"
|
10
|
-
require "dry/monads/constants"
|
11
|
-
|
12
3
|
module Dry
|
13
4
|
module Monads
|
14
5
|
# Represents a value which can exist or not, i.e. it could be nil.
|
@@ -127,8 +118,8 @@ module Dry
|
|
127
118
|
# @param args [Array<Object>] arguments will be transparently passed through to #bind
|
128
119
|
# @return [Maybe::Some, Maybe::None] Wrapped result, i.e. nil will be mapped to None,
|
129
120
|
# other values will be wrapped with Some
|
130
|
-
def fmap(
|
131
|
-
next_value = bind(
|
121
|
+
def fmap(...)
|
122
|
+
next_value = bind(...)
|
132
123
|
|
133
124
|
if next_value.nil?
|
134
125
|
if self.class.warn_on_implicit_nil_coercion
|
@@ -140,7 +131,7 @@ module Dry
|
|
140
131
|
"You can opt out of these warnings with\n"\
|
141
132
|
"Dry::Monads::Maybe.warn_on_implicit_nil_coercion false",
|
142
133
|
uplevel: 0,
|
143
|
-
tag: :
|
134
|
+
tag: :"dry-monads"
|
144
135
|
)
|
145
136
|
end
|
146
137
|
Monads.None()
|
@@ -160,8 +151,8 @@ module Dry
|
|
160
151
|
# @param args [Array<Object>] arguments will be transparently passed through to #bind
|
161
152
|
# @return [Maybe::Some, Maybe::None] Wrapped result, i.e. nil will be mapped to None,
|
162
153
|
# other values will be wrapped with Some
|
163
|
-
def maybe(
|
164
|
-
Maybe.coerce(bind(
|
154
|
+
def maybe(...)
|
155
|
+
Maybe.coerce(bind(...))
|
165
156
|
end
|
166
157
|
|
167
158
|
# Accepts a block and runs it against the wrapped value.
|
@@ -201,7 +192,7 @@ module Dry
|
|
201
192
|
include RightBiased::Left
|
202
193
|
|
203
194
|
@instance = new.freeze
|
204
|
-
singleton_class.
|
195
|
+
singleton_class.attr_reader(:instance)
|
205
196
|
|
206
197
|
# @api private
|
207
198
|
def self.method_missing(m, *) # rubocop:disable Style/MissingRespondToMissing
|
@@ -255,8 +246,8 @@ module Dry
|
|
255
246
|
# @param args [Array<Object>] arguments will be passed to the underlying `#or` call
|
256
247
|
# @return [Maybe::Some, Maybe::None] Lifted `#or` result, i.e. nil will be mapped to None,
|
257
248
|
# other values will be wrapped with Some
|
258
|
-
def or_fmap(
|
259
|
-
Maybe.coerce(self.or(
|
249
|
+
def or_fmap(...)
|
250
|
+
Maybe.coerce(self.or(...))
|
260
251
|
end
|
261
252
|
|
262
253
|
# @return [String]
|
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
|
@@ -20,10 +20,8 @@ module Dry
|
|
20
20
|
if error === value
|
21
21
|
Failure.new(value, RightBiased::Left.trace_caller)
|
22
22
|
else
|
23
|
-
# rubocop:disable Style/RaiseArgs
|
24
23
|
# per https://github.com/dry-rb/dry-monads/pull/142
|
25
24
|
raise InvalidFailureTypeError.new(value)
|
26
|
-
# rubocop:enable Style/RaiseArgs
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
data/lib/dry/monads/result.rb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/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.
|
@@ -116,8 +108,8 @@ module Dry
|
|
116
108
|
#
|
117
109
|
# @param args [Array<Object>] arguments will be transparently passed through to #bind
|
118
110
|
# @return [Result::Success]
|
119
|
-
def fmap(
|
120
|
-
Success.new(bind(
|
111
|
+
def fmap(...)
|
112
|
+
Success.new(bind(...))
|
121
113
|
end
|
122
114
|
|
123
115
|
# Returns result of applying first function to the internal value.
|
@@ -164,7 +156,7 @@ module Dry
|
|
164
156
|
include RightBiased::Left
|
165
157
|
include Dry::Equalizer(:failure)
|
166
158
|
|
167
|
-
singleton_class.
|
159
|
+
singleton_class.alias_method(:call, :new)
|
168
160
|
|
169
161
|
# Shortcut for Failure([...])
|
170
162
|
#
|
@@ -251,8 +243,8 @@ module Dry
|
|
251
243
|
#
|
252
244
|
# @param args [Array<Object>] arguments will be passed to the underlying `#or` call
|
253
245
|
# @return [Result::Success] Wrapped value
|
254
|
-
def or_fmap(
|
255
|
-
Success.new(self.or(
|
246
|
+
def or_fmap(...)
|
247
|
+
Success.new(self.or(...))
|
256
248
|
end
|
257
249
|
|
258
250
|
# @return [String]
|
@@ -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.
|
@@ -12,7 +7,7 @@ module Dry
|
|
12
7
|
# Right part
|
13
8
|
#
|
14
9
|
# @api public
|
15
|
-
module Right
|
10
|
+
module Right
|
16
11
|
# @private
|
17
12
|
def self.included(m)
|
18
13
|
super
|
@@ -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.
|
@@ -133,7 +128,7 @@ module Dry
|
|
133
128
|
raise TypeError, "Cannot apply #{val.inspect} to #{@value.inspect}"
|
134
129
|
end
|
135
130
|
|
136
|
-
Undefined.default(val, &block).fmap {
|
131
|
+
Undefined.default(val, &block).fmap { curry.(_1) }
|
137
132
|
end
|
138
133
|
|
139
134
|
# @param other [Object]
|
@@ -236,19 +231,12 @@ module Dry
|
|
236
231
|
|
237
232
|
private
|
238
233
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
[[value], EMPTY_HASH]
|
246
|
-
end
|
247
|
-
end
|
248
|
-
else
|
249
|
-
# @api private
|
250
|
-
def destructure(*args, **kwargs)
|
251
|
-
[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]
|
252
240
|
end
|
253
241
|
end
|
254
242
|
|
data/lib/dry/monads/task.rb
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
|
3
3
|
require "concurrent/promise"
|
4
4
|
|
5
|
-
require "dry/monads/unit"
|
6
|
-
require "dry/monads/curry"
|
7
|
-
require "dry/monads/conversion_stubs"
|
8
|
-
|
9
5
|
module Dry
|
10
6
|
module Monads
|
11
7
|
# The Task monad represents an async computation. The implementation
|
@@ -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
|
@@ -83,6 +79,7 @@ module Dry
|
|
83
79
|
end
|
84
80
|
|
85
81
|
include ConversionStubs[:to_maybe, :to_result]
|
82
|
+
extend ::Dry::Core::Deprecations[:"dry-monads"]
|
86
83
|
|
87
84
|
# @api private
|
88
85
|
attr_reader :promise
|
@@ -124,9 +121,9 @@ module Dry
|
|
124
121
|
# and returns another task
|
125
122
|
# @return [Task]
|
126
123
|
def bind(&block)
|
127
|
-
self.class.new(promise.flat_map {
|
124
|
+
self.class.new(promise.flat_map { block.(_1).promise })
|
128
125
|
end
|
129
|
-
|
126
|
+
deprecate :then, :bind
|
130
127
|
|
131
128
|
# @return [String]
|
132
129
|
def to_s
|
@@ -168,12 +165,12 @@ module Dry
|
|
168
165
|
promise.on_error do |v|
|
169
166
|
inner = block.(v).promise
|
170
167
|
inner.execute
|
171
|
-
inner.on_success {
|
172
|
-
inner.on_error {
|
168
|
+
inner.on_success { child.on_fulfill(_1) }
|
169
|
+
inner.on_error { child.on_reject(_1) }
|
173
170
|
rescue StandardError => e
|
174
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
|
@@ -238,7 +235,7 @@ module Dry
|
|
238
235
|
# @return [Task]
|
239
236
|
def apply(val = Undefined, &block)
|
240
237
|
arg = Undefined.default(val, &block)
|
241
|
-
bind { |f| arg.fmap {
|
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.
|
data/lib/dry/monads/traverse.rb
CHANGED
data/lib/dry/monads/try.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/equalizer"
|
4
|
-
require "dry/core/deprecations"
|
5
|
-
|
6
|
-
require "dry/monads/right_biased"
|
7
|
-
require "dry/monads/conversion_stubs"
|
8
|
-
|
9
3
|
module Dry
|
10
4
|
module Monads
|
11
5
|
# Represents a value which can be either success or a failure (an exception).
|
@@ -135,7 +129,7 @@ module Dry
|
|
135
129
|
# object and the rest of args will be passed
|
136
130
|
# to this object along with the internal value
|
137
131
|
# @return [Object, Try::Error]
|
138
|
-
def bind(
|
132
|
+
def bind(...)
|
139
133
|
super
|
140
134
|
rescue *catchable => e
|
141
135
|
Error.new(e)
|
@@ -153,8 +147,8 @@ module Dry
|
|
153
147
|
# @param args [Array<Object>] extra arguments for the block, arguments are being processes
|
154
148
|
# just as in #bind
|
155
149
|
# @return [Try::Value, Try::Error]
|
156
|
-
def fmap(
|
157
|
-
Value.new(catchable, bind_call(
|
150
|
+
def fmap(...)
|
151
|
+
Value.new(catchable, bind_call(...))
|
158
152
|
rescue *catchable => e
|
159
153
|
Error.new(e)
|
160
154
|
end
|
@@ -186,7 +180,7 @@ module Dry
|
|
186
180
|
include Dry::Equalizer(:exception)
|
187
181
|
include RightBiased::Left
|
188
182
|
|
189
|
-
singleton_class.
|
183
|
+
singleton_class.alias_method(:call, :new)
|
190
184
|
|
191
185
|
# @param exception [Exception]
|
192
186
|
def initialize(exception)
|
@@ -238,7 +232,7 @@ module Dry
|
|
238
232
|
classes = errors
|
239
233
|
end
|
240
234
|
|
241
|
-
if classes.any? {
|
235
|
+
if classes.any? { _1 === exception }
|
242
236
|
Value.new([exception.class], yield(exception))
|
243
237
|
else
|
244
238
|
self
|
data/lib/dry/monads/unit.rb
CHANGED
@@ -18,7 +18,7 @@ module Dry
|
|
18
18
|
# Maybe(Unit)
|
19
19
|
# => Some(Unit)
|
20
20
|
#
|
21
|
-
Unit = Object.new.tap do |unit|
|
21
|
+
Unit = ::Object.new.tap do |unit|
|
22
22
|
def unit.to_s
|
23
23
|
"Unit"
|
24
24
|
end
|
@@ -30,6 +30,8 @@ module Dry
|
|
30
30
|
def unit.deconstruct
|
31
31
|
EMPTY_ARRAY
|
32
32
|
end
|
33
|
+
|
34
|
+
unit.freeze
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
data/lib/dry/monads/validated.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/monads/conversion_stubs"
|
4
|
-
require "dry/monads/constants"
|
5
|
-
require "dry/monads/right_biased"
|
6
|
-
|
7
3
|
module Dry
|
8
4
|
module Monads
|
9
5
|
# Validated is similar to Result and represents an outcome of a validation.
|
@@ -175,7 +171,7 @@ module Dry
|
|
175
171
|
def apply(val = Undefined, &block)
|
176
172
|
Undefined
|
177
173
|
.default(val, &block)
|
178
|
-
.alt_map {
|
174
|
+
.alt_map { @error + _1 }
|
179
175
|
.fmap { return self }
|
180
176
|
end
|
181
177
|
|
data/lib/dry/monads/version.rb
CHANGED
data/lib/dry/monads.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "concurrent/map"
|
4
|
+
require "zeitwerk"
|
5
|
+
require "dry/core"
|
6
|
+
require "dry/monads/constants"
|
7
|
+
require "dry/monads/errors"
|
4
8
|
require "dry/monads/registry"
|
5
9
|
|
6
10
|
module Dry
|
@@ -8,6 +12,21 @@ module Dry
|
|
8
12
|
#
|
9
13
|
# @api public
|
10
14
|
module Monads
|
15
|
+
# @api private
|
16
|
+
def self.loader
|
17
|
+
@loader ||= Zeitwerk::Loader.new.tap do |loader|
|
18
|
+
root = File.expand_path("..", __dir__)
|
19
|
+
loader.tag = "dry-monads"
|
20
|
+
loader.inflector = Zeitwerk::GemInflector.new("#{root}/dry-monads.rb")
|
21
|
+
loader.push_dir(root)
|
22
|
+
loader.ignore(
|
23
|
+
"#{root}/dry-monads.rb",
|
24
|
+
"#{root}/dry/monads/{all,constants,errors,registry,version}.rb",
|
25
|
+
"#{root}/json/**/*.rb"
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
11
30
|
# @private
|
12
31
|
def self.included(base)
|
13
32
|
if all_loaded?
|
@@ -49,10 +68,12 @@ module Dry
|
|
49
68
|
def self.[](*monads)
|
50
69
|
monads.sort!
|
51
70
|
@mixins.fetch_or_store(monads.hash) do
|
52
|
-
monads.each {
|
53
|
-
mixins = monads.map {
|
71
|
+
monads.each { load_monad(_1) }
|
72
|
+
mixins = monads.map { registry.fetch(_1) }
|
54
73
|
::Module.new { include(*mixins) }.freeze
|
55
74
|
end
|
56
75
|
end
|
76
|
+
|
77
|
+
loader.setup
|
57
78
|
end
|
58
79
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-monads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikita Shilnikov
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -30,42 +30,48 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
33
|
+
version: '1.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '2'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
43
|
+
version: '1.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
48
|
+
name: zeitwerk
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
|
-
- - "
|
51
|
+
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
type: :
|
53
|
+
version: '2.6'
|
54
|
+
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
|
-
- - "
|
58
|
+
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
60
|
+
version: '2.6'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
62
|
+
name: bundler
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
65
|
- - ">="
|
60
66
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0
|
67
|
+
version: '0'
|
62
68
|
type: :development
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
72
|
- - ">="
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0
|
74
|
+
version: '0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: rake
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +120,6 @@ files:
|
|
114
120
|
- lib/dry/monads/do.rb
|
115
121
|
- lib/dry/monads/do/all.rb
|
116
122
|
- lib/dry/monads/do/mixin.rb
|
117
|
-
- lib/dry/monads/either.rb
|
118
123
|
- lib/dry/monads/errors.rb
|
119
124
|
- lib/dry/monads/lazy.rb
|
120
125
|
- lib/dry/monads/list.rb
|
@@ -136,10 +141,10 @@ licenses:
|
|
136
141
|
- MIT
|
137
142
|
metadata:
|
138
143
|
allowed_push_host: https://rubygems.org
|
139
|
-
changelog_uri: https://github.com/dry-rb/dry-monads/blob/
|
144
|
+
changelog_uri: https://github.com/dry-rb/dry-monads/blob/main/CHANGELOG.md
|
140
145
|
source_code_uri: https://github.com/dry-rb/dry-monads
|
141
146
|
bug_tracker_uri: https://github.com/dry-rb/dry-monads/issues
|
142
|
-
post_install_message:
|
147
|
+
post_install_message:
|
143
148
|
rdoc_options: []
|
144
149
|
require_paths:
|
145
150
|
- lib
|
@@ -147,15 +152,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
152
|
requirements:
|
148
153
|
- - ">="
|
149
154
|
- !ruby/object:Gem::Version
|
150
|
-
version: 2.
|
155
|
+
version: 2.7.0
|
151
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
157
|
requirements:
|
153
158
|
- - ">="
|
154
159
|
- !ruby/object:Gem::Version
|
155
160
|
version: '0'
|
156
161
|
requirements: []
|
157
|
-
rubygems_version: 3.
|
158
|
-
signing_key:
|
162
|
+
rubygems_version: 3.1.6
|
163
|
+
signing_key:
|
159
164
|
specification_version: 4
|
160
165
|
summary: Common monads for Ruby
|
161
166
|
test_files: []
|
data/lib/dry/monads/either.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "dry/core/deprecations"
|
4
|
-
|
5
|
-
Dry::Core::Deprecations.warn("Either monad was renamed to Result", tag: :"dry-monads")
|
6
|
-
|
7
|
-
require "dry/monads/result"
|
8
|
-
|
9
|
-
module Dry
|
10
|
-
module Monads
|
11
|
-
Either = Result
|
12
|
-
deprecate_constant :Either
|
13
|
-
|
14
|
-
class Result
|
15
|
-
extend ::Dry::Core::Deprecations[:"dry-monads"]
|
16
|
-
|
17
|
-
deprecate :to_either, :to_result
|
18
|
-
|
19
|
-
Right = Success
|
20
|
-
Left = Failure
|
21
|
-
|
22
|
-
deprecate_constant :Right
|
23
|
-
deprecate_constant :Left
|
24
|
-
|
25
|
-
module Mixin
|
26
|
-
module Constructors
|
27
|
-
extend Dry::Core::Deprecations[:"dry-monads"]
|
28
|
-
|
29
|
-
Right = Success
|
30
|
-
Left = Failure
|
31
|
-
deprecate_constant :Right
|
32
|
-
deprecate_constant :Left
|
33
|
-
|
34
|
-
deprecate :Right, :Success
|
35
|
-
deprecate :Left, :Failure
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Success
|
40
|
-
deprecate :left?, :failure?
|
41
|
-
deprecate :right?, :success?
|
42
|
-
end
|
43
|
-
|
44
|
-
class Failure
|
45
|
-
deprecate :left?, :failure?
|
46
|
-
deprecate :right?, :success?
|
47
|
-
|
48
|
-
deprecate :left, :failure
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class Try
|
53
|
-
class Value
|
54
|
-
extend Dry::Core::Deprecations[:"dry-monads"]
|
55
|
-
|
56
|
-
deprecate :to_either, :to_result
|
57
|
-
end
|
58
|
-
|
59
|
-
class Error
|
60
|
-
extend Dry::Core::Deprecations[:"dry-monads"]
|
61
|
-
|
62
|
-
deprecate :to_either, :to_result
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|