dry-monads 1.3.2 → 1.4.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 +157 -73
- data/LICENSE +1 -1
- data/README.md +18 -38
- data/dry-monads.gemspec +32 -30
- data/lib/dry-monads.rb +3 -1
- data/lib/dry/monads.rb +4 -2
- data/lib/dry/monads/all.rb +4 -2
- data/lib/dry/monads/constants.rb +1 -1
- data/lib/dry/monads/conversion_stubs.rb +2 -0
- data/lib/dry/monads/curry.rb +2 -0
- data/lib/dry/monads/do.rb +55 -17
- data/lib/dry/monads/do/all.rb +39 -17
- data/lib/dry/monads/do/mixin.rb +2 -0
- data/lib/dry/monads/either.rb +9 -7
- data/lib/dry/monads/errors.rb +8 -3
- data/lib/dry/monads/lazy.rb +19 -6
- data/lib/dry/monads/list.rb +31 -30
- data/lib/dry/monads/maybe.rb +90 -19
- data/lib/dry/monads/registry.rb +15 -12
- data/lib/dry/monads/result.rb +42 -15
- data/lib/dry/monads/result/fixed.rb +35 -24
- data/lib/dry/monads/right_biased.rb +45 -24
- data/lib/dry/monads/task.rb +25 -22
- data/lib/dry/monads/transformer.rb +4 -1
- data/lib/dry/monads/traverse.rb +9 -1
- data/lib/dry/monads/try.rb +51 -13
- data/lib/dry/monads/unit.rb +6 -2
- data/lib/dry/monads/validated.rb +27 -20
- data/lib/dry/monads/version.rb +3 -1
- data/lib/json/add/dry/monads/maybe.rb +4 -3
- metadata +27 -75
- 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 -34
- data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
- data/.github/workflows/ci.yml +0 -74
- data/.github/workflows/docsite.yml +0 -34
- data/.github/workflows/sync_configs.yml +0 -34
- data/.gitignore +0 -10
- data/.rspec +0 -4
- data/.rubocop.yml +0 -89
- data/.yardopts +0 -4
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -23
- data/Rakefile +0 -6
- data/bin/console +0 -16
- 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/log/.gitkeep +0 -0
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,50 +1,30 @@
|
|
1
|
-
|
1
|
+
<!--- this file is synced from dry-rb/template-gem project -->
|
2
2
|
[gem]: https://rubygems.org/gems/dry-monads
|
3
|
-
[
|
4
|
-
[
|
5
|
-
[inch]: http://inch-ci.org/github/dry-rb/dry-monads
|
3
|
+
[actions]: https://github.com/dry-rb/dry-monads/actions
|
4
|
+
[codacy]: https://www.codacy.com/gh/dry-rb/dry-monads
|
6
5
|
[chat]: https://dry-rb.zulipchat.com
|
6
|
+
[inchpages]: http://inch-ci.org/github/dry-rb/dry-monads
|
7
7
|
|
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
|
-
[![Gem Version](https://
|
11
|
-
[![
|
12
|
-
[![
|
13
|
-
[![
|
14
|
-
[![
|
15
|
-
|
16
|
-
Monads for Ruby.
|
17
|
-
|
18
|
-
## Installation
|
19
|
-
|
20
|
-
Add this line to your application's Gemfile:
|
21
|
-
|
22
|
-
```ruby
|
23
|
-
gem 'dry-monads'
|
24
|
-
```
|
25
|
-
|
26
|
-
And then execute:
|
27
|
-
|
28
|
-
```sh
|
29
|
-
$ bundle
|
30
|
-
```
|
31
|
-
|
32
|
-
Or install it yourself as:
|
33
|
-
|
34
|
-
```sh
|
35
|
-
$ gem install dry-monads
|
36
|
-
```
|
10
|
+
[![Gem Version](https://badge.fury.io/rb/dry-monads.svg)][gem]
|
11
|
+
[![CI Status](https://github.com/dry-rb/dry-monads/workflows/CI/badge.svg)][actions]
|
12
|
+
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f2eed41bf7f04b38b0a7691c2cf6e73c)][codacy]
|
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=master)][inchpages]
|
37
15
|
|
38
16
|
## Links
|
39
17
|
|
40
|
-
|
18
|
+
* [User documentation](https://dry-rb.org/gems/dry-monads)
|
19
|
+
* [API documentation](http://rubydoc.info/gems/dry-monads)
|
20
|
+
|
21
|
+
## Supported Ruby versions
|
41
22
|
|
42
|
-
|
23
|
+
This library officially supports the following Ruby versions:
|
43
24
|
|
44
|
-
|
45
|
-
|
46
|
-
prompt that will allow you to experiment.
|
25
|
+
* MRI `>= 2.6.0`
|
26
|
+
* ~~jruby~~ `>= 9.3` (we are waiting for [2.6 support](https://github.com/jruby/jruby/issues/6161))
|
47
27
|
|
48
|
-
##
|
28
|
+
## License
|
49
29
|
|
50
|
-
|
30
|
+
See `LICENSE` file.
|
data/dry-monads.gemspec
CHANGED
@@ -1,37 +1,39 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this file is synced from dry-rb/template-gem project
|
4
|
+
|
5
|
+
lib = File.expand_path("lib", __dir__)
|
2
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
7
|
+
require "dry/monads/version"
|
4
8
|
|
5
9
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
10
|
+
spec.name = "dry-monads"
|
11
|
+
spec.authors = ["Nikita Shilnikov"]
|
12
|
+
spec.email = ["fg@flashgordon.ru"]
|
13
|
+
spec.license = "MIT"
|
7
14
|
spec.version = Dry::Monads::VERSION.dup
|
8
|
-
spec.authors = ['Nikita Shilnikov']
|
9
|
-
spec.email = ['fg@flashgordon.ru']
|
10
|
-
spec.license = 'MIT'
|
11
15
|
|
12
|
-
spec.summary =
|
16
|
+
spec.summary = "Common monads for Ruby"
|
13
17
|
spec.description = spec.summary
|
14
|
-
spec.homepage =
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
spec.
|
26
|
-
|
27
|
-
|
28
|
-
spec.
|
29
|
-
spec.
|
30
|
-
|
31
|
-
spec.
|
32
|
-
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency 'rspec'
|
36
|
-
spec.add_development_dependency 'dry-types', '>= 0.12'
|
18
|
+
spec.homepage = "https://dry-rb.org/gems/dry-monads"
|
19
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-monads.gemspec", "lib/**/*"]
|
20
|
+
spec.bindir = "bin"
|
21
|
+
spec.executables = []
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-monads/blob/master/CHANGELOG.md"
|
26
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-monads"
|
27
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-monads/issues"
|
28
|
+
|
29
|
+
spec.required_ruby_version = ">= 2.6.0"
|
30
|
+
|
31
|
+
# to update dependencies edit project.yml
|
32
|
+
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
33
|
+
spec.add_runtime_dependency "dry-core", "~> 0.7"
|
34
|
+
|
35
|
+
spec.add_development_dependency "bundler"
|
36
|
+
spec.add_development_dependency "dry-types", ">= 0.1.2"
|
37
|
+
spec.add_development_dependency "rake"
|
38
|
+
spec.add_development_dependency "rspec"
|
37
39
|
end
|
data/lib/dry-monads.rb
CHANGED
data/lib/dry/monads.rb
CHANGED
data/lib/dry/monads/all.rb
CHANGED
data/lib/dry/monads/constants.rb
CHANGED
data/lib/dry/monads/curry.rb
CHANGED
data/lib/dry/monads/do.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads/list"
|
4
|
+
require "dry/monads/do/mixin"
|
5
|
+
require "dry/monads/constants"
|
4
6
|
|
5
7
|
module Dry
|
6
8
|
module Monads
|
@@ -10,6 +12,14 @@ module Dry
|
|
10
12
|
module Do
|
11
13
|
extend Mixin
|
12
14
|
|
15
|
+
DELEGATE = ::RUBY_VERSION < "2.7" ? "*" : "..."
|
16
|
+
|
17
|
+
VISIBILITY_WORD = {
|
18
|
+
public: "",
|
19
|
+
private: "private ",
|
20
|
+
protected: "protected "
|
21
|
+
}.freeze
|
22
|
+
|
13
23
|
# @api private
|
14
24
|
class Halt < StandardError
|
15
25
|
# @api private
|
@@ -22,6 +32,25 @@ module Dry
|
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
35
|
+
# @api private
|
36
|
+
class MethodTracker < ::Module
|
37
|
+
# @api private
|
38
|
+
def initialize(tracked_methods, base, wrapper)
|
39
|
+
module_eval do
|
40
|
+
private
|
41
|
+
|
42
|
+
define_method(:method_added) do |method|
|
43
|
+
super(method)
|
44
|
+
|
45
|
+
if tracked_methods.include?(method)
|
46
|
+
visibility = Do.method_visibility(base, method)
|
47
|
+
Do.wrap_method(wrapper, method, visibility)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
25
54
|
class << self
|
26
55
|
# Generates a module that passes a block to methods
|
27
56
|
# that either unwraps a single-valued monadic value or halts
|
@@ -80,13 +109,11 @@ module Dry
|
|
80
109
|
# @param [Array<Symbol>] methods
|
81
110
|
# @return [Module]
|
82
111
|
def for(*methods)
|
83
|
-
mod = ::Module.new do
|
84
|
-
methods.each { |method_name| Do.wrap_method(self, method_name) }
|
85
|
-
end
|
86
|
-
|
87
112
|
::Module.new do
|
88
113
|
singleton_class.send(:define_method, :included) do |base|
|
114
|
+
mod = ::Module.new
|
89
115
|
base.prepend(mod)
|
116
|
+
base.extend(MethodTracker.new(methods, base, mod))
|
90
117
|
end
|
91
118
|
end
|
92
119
|
end
|
@@ -96,23 +123,34 @@ module Dry
|
|
96
123
|
super
|
97
124
|
|
98
125
|
# Actually mixes in Do::All
|
99
|
-
require
|
126
|
+
require "dry/monads/do/all"
|
100
127
|
base.include All
|
101
128
|
end
|
102
129
|
|
103
130
|
# @api private
|
104
|
-
def wrap_method(target,
|
131
|
+
def wrap_method(target, method, visibility)
|
105
132
|
target.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
106
|
-
def #{
|
107
|
-
if block_given?
|
108
|
-
super
|
109
|
-
else
|
110
|
-
Do.() { super { |*ms| Do.bind(ms) } }
|
111
|
-
end
|
112
|
-
end
|
133
|
+
#{VISIBILITY_WORD[visibility]} def #{method}(#{DELEGATE}) # private def create_acccount(...)
|
134
|
+
if block_given? # if block_given?
|
135
|
+
super # super
|
136
|
+
else # else
|
137
|
+
Do.() { super { |*ms| Do.bind(ms) } } # Do.() { super { |*ms| Do.bind(ms) } }
|
138
|
+
end # end
|
139
|
+
end # end
|
113
140
|
RUBY
|
114
141
|
end
|
115
142
|
|
143
|
+
# @api private
|
144
|
+
def method_visibility(mod, method)
|
145
|
+
if mod.public_method_defined?(method)
|
146
|
+
:public
|
147
|
+
elsif mod.private_method_defined?(method)
|
148
|
+
:private
|
149
|
+
else
|
150
|
+
:protected
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
116
154
|
# @api private
|
117
155
|
def coerce_to_monad(monads)
|
118
156
|
return monads if monads.size != 1
|
@@ -131,7 +169,7 @@ module Dry
|
|
131
169
|
|
132
170
|
# @api private
|
133
171
|
def halt(result)
|
134
|
-
raise Halt.new(result),
|
172
|
+
raise Halt.new(result), "", []
|
135
173
|
end
|
136
174
|
end
|
137
175
|
end
|
data/lib/dry/monads/do/all.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads/do"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Monads
|
@@ -66,9 +68,10 @@ module Dry
|
|
66
68
|
tracker = self
|
67
69
|
|
68
70
|
module_eval do
|
71
|
+
private
|
72
|
+
|
69
73
|
define_method(:method_added) do |method|
|
70
74
|
super(method)
|
71
|
-
|
72
75
|
tracker.wrap_method(self, method)
|
73
76
|
end
|
74
77
|
|
@@ -91,20 +94,37 @@ module Dry
|
|
91
94
|
end
|
92
95
|
|
93
96
|
def wrap_method(target, method)
|
94
|
-
Do.
|
97
|
+
visibility = Do.method_visibility(target, method)
|
98
|
+
Do.wrap_method(wrappers[target], method, visibility)
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
98
|
-
|
99
|
-
|
100
|
-
|
102
|
+
class << self
|
103
|
+
# @api private
|
104
|
+
def included(base)
|
105
|
+
super
|
101
106
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
107
|
+
wrappers = ::Hash.new { |h, k| h[k] = ::Module.new }
|
108
|
+
tracker = MethodTracker.new(wrappers)
|
109
|
+
base.extend(tracker)
|
110
|
+
base.extend(InstanceMixin) unless base.is_a?(::Class)
|
111
|
+
wrap_defined_methods(base, wrappers[base])
|
112
|
+
end
|
106
113
|
|
107
|
-
|
114
|
+
# @api private
|
115
|
+
def wrap_defined_methods(klass, target)
|
116
|
+
klass.public_instance_methods(false).each do |m|
|
117
|
+
Do.wrap_method(target, m, :public)
|
118
|
+
end
|
119
|
+
|
120
|
+
klass.protected_instance_methods(false).each do |m|
|
121
|
+
Do.wrap_method(target, m, :protected)
|
122
|
+
end
|
123
|
+
|
124
|
+
klass.private_instance_methods(false).each do |m|
|
125
|
+
Do.wrap_method(target, m, :private)
|
126
|
+
end
|
127
|
+
end
|
108
128
|
end
|
109
129
|
|
110
130
|
# @api private
|
@@ -114,16 +134,18 @@ module Dry
|
|
114
134
|
super
|
115
135
|
|
116
136
|
wrapper = ::Module.new
|
117
|
-
object.singleton_class
|
137
|
+
eigenclass = object.singleton_class
|
138
|
+
eigenclass.prepend(wrapper)
|
118
139
|
object.define_singleton_method(:singleton_method_added) do |method|
|
119
140
|
super(method)
|
120
141
|
|
121
142
|
next if method.equal?(:singleton_method_added)
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
Do.wrap_method(wrapper, m)
|
143
|
+
|
144
|
+
visibility = Do.method_visibility(eigenclass, method)
|
145
|
+
Do.wrap_method(wrapper, method, visibility)
|
126
146
|
end
|
147
|
+
|
148
|
+
All.wrap_defined_methods(eigenclass, wrapper)
|
127
149
|
end
|
128
150
|
end
|
129
151
|
|
@@ -131,7 +153,7 @@ module Dry
|
|
131
153
|
end
|
132
154
|
end
|
133
155
|
|
134
|
-
require
|
156
|
+
require "dry/monads/registry"
|
135
157
|
register_mixin(:do, Do::All)
|
136
158
|
end
|
137
159
|
end
|
data/lib/dry/monads/do/mixin.rb
CHANGED
data/lib/dry/monads/either.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "dry/core/deprecations"
|
4
4
|
|
5
|
-
|
5
|
+
Dry::Core::Deprecations.warn("Either monad was renamed to Result", tag: :"dry-monads")
|
6
|
+
|
7
|
+
require "dry/monads/result"
|
6
8
|
|
7
9
|
module Dry
|
8
10
|
module Monads
|
@@ -10,7 +12,7 @@ module Dry
|
|
10
12
|
deprecate_constant :Either
|
11
13
|
|
12
14
|
class Result
|
13
|
-
extend Dry::Core::Deprecations[:
|
15
|
+
extend ::Dry::Core::Deprecations[:"dry-monads"]
|
14
16
|
|
15
17
|
deprecate :to_either, :to_result
|
16
18
|
|
@@ -22,7 +24,7 @@ module Dry
|
|
22
24
|
|
23
25
|
module Mixin
|
24
26
|
module Constructors
|
25
|
-
extend Dry::Core::Deprecations[:
|
27
|
+
extend Dry::Core::Deprecations[:"dry-monads"]
|
26
28
|
|
27
29
|
Right = Success
|
28
30
|
Left = Failure
|
@@ -49,13 +51,13 @@ module Dry
|
|
49
51
|
|
50
52
|
class Try
|
51
53
|
class Value
|
52
|
-
extend Dry::Core::Deprecations[:
|
54
|
+
extend Dry::Core::Deprecations[:"dry-monads"]
|
53
55
|
|
54
56
|
deprecate :to_either, :to_result
|
55
57
|
end
|
56
58
|
|
57
59
|
class Error
|
58
|
-
extend Dry::Core::Deprecations[:
|
60
|
+
extend Dry::Core::Deprecations[:"dry-monads"]
|
59
61
|
|
60
62
|
deprecate :to_either, :to_result
|
61
63
|
end
|