dry-monads 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 613808228df63dd17a3199ed374ed227b5286340
4
- data.tar.gz: df17cfd8dafdee56feb611a0acae4dca01c6a17c
3
+ metadata.gz: 90f99efaec5f7f88c8f150a6af7d9f3ee2bc2a64
4
+ data.tar.gz: 82c6bb698fa47243c44367c14ab182d893c0b59c
5
5
  SHA512:
6
- metadata.gz: be3207f4e98696f3f4abc2f9b72d3c912198a1581492a9190c6d6388d86613484b6577db46138e2725cf2e6bdf078150ba8185586a1d0a8e66e4d528ab6c163d
7
- data.tar.gz: 5349bf6489ed7ec11b1300858e74a321ec963a7475465560a49318200286632fad5c06dda39e525cf6d7f5d05d3ce56bf5af776dd23543bb7bb123d8f3d066a4
6
+ metadata.gz: 559a48263fd284e9c93c1773846b66960653a37ca811b249f5482a1cc518aa83a40e71e7adb5d206c50066293e353317793cb68893935c37f8f12a36654ad854
7
+ data.tar.gz: 8c06400c56a9b753d83df82cd011477cc29ba492a3383d1df325e9fa7eaafd56bef653590cde58c4b415994c63817eac1574b12a769267cf2060ab8c0eead8d5
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ log/
@@ -2,32 +2,24 @@ language: ruby
2
2
  dist: trusty
3
3
  sudo: false
4
4
  cache: bundler
5
- bundler_args: --without benchmarks
5
+ bundler_args: --without benchmarks docs
6
6
  script:
7
7
  - bundle exec rake spec
8
8
  after_success:
9
- # Send coverage report from the job #1 == current MRI release
10
- - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
9
+ - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
11
10
  rvm:
12
- - 2.4.0
13
- - 2.3.3
14
- - 2.2.6
15
- - 2.1.10
16
- - jruby-9.1.7.0
11
+ - 2.2.8
12
+ - 2.3.5
13
+ - 2.4.2
14
+ - jruby-9.1.13.0
17
15
  - ruby-head
18
16
  env:
19
17
  global:
20
18
  - JRUBY_OPTS='--dev -J-Xmx1024M'
19
+ - COVERAGE=true
21
20
  matrix:
22
21
  allow_failures:
23
22
  - rvm: ruby-head
24
- - rvm: jruby-head
25
- - rvm: rbx-3
26
- include:
27
- - rvm: jruby-head
28
- before_install: gem update bundler
29
- - rvm: rbx-3
30
- before_install: gem update bundler
31
23
 
32
24
  notifications:
33
25
  email:
@@ -0,0 +1,4 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
3
+ --plugin junk
4
+ lib/**/*.rb
@@ -1,10 +1,39 @@
1
+ # v0.4.0 2017-11-11
2
+
3
+ ## Changed
4
+
5
+ * The `Either` monad was renamed to `Result` which sounds less nerdy but better reflects the purpose of the type. `Either::Right` became `Result::Success` and `Either::Left` became `Result::Failure`. This change is backward-compatible overall but you will see the new names when using old `Left` and `Right` methods (citizen428)
6
+ * Consequently, `Try::Success` and `Try::Failure` were renamed to `Try::Value` and `Try::Error` (flash-gordon)
7
+
8
+ ## Added
9
+
10
+ * `Try#or`, works as `Result#or` (flash-gordon)
11
+ * `Maybe#success?` and `Maybe#failure?` (aliases for `#some?` and `#none?`) (flash-gordon)
12
+ * `Either#flip` inverts a `Result` value (flash-gordon)
13
+ * `List#map` called without a block returns an `Enumerator` object (flash-gordon)
14
+ * Right-biased monads (`Maybe`, `Result`, and `Try`) now implement the `===` operator which is used for equality checks in the `case` statement (flash-gordon)
15
+ ```ruby
16
+ case value
17
+ when Some(1..100) then :ok
18
+ when Some { |x| x < 0 } then :negative
19
+ when Some(Integer) then :invalid
20
+ else raise TypeError
21
+ end
22
+ ```
23
+
24
+ ## Deprecated
25
+
26
+ * Direct accessing `value` on right-biased monads has been deprecated, use the `value!` method instead. `value!` will raise an exception if it is called on a Sailure/None/Error instance (flash-gordon)
27
+
28
+ [Compare v0.3.1...v0.4.0](https://github.com/dry-rb/dry-monads/compare/v0.3.1...v0.4.0)
29
+
1
30
  # v0.3.1 2017-03-18
2
31
 
3
32
  ## Fixed
4
33
 
5
34
  * Fixed unexpected coercing to `Hash` on `.bind` call (flash-gordon)
6
35
 
7
- [Compare v0.3.1...v0.3.0](https://github.com/dry-rb/dry-monads/compare/v0.3.0...v0.3.1)
36
+ [Compare v0.3.0...v0.3.1](https://github.com/dry-rb/dry-monads/compare/v0.3.0...v0.3.1)
8
37
 
9
38
  # v0.3.0 2017-03-16
10
39
 
@@ -17,7 +46,7 @@
17
46
  * Added `List#traverse` that "flips" the list with an embedded monad (flash-gordon + damncabbage)
18
47
  * Added `#tee` for all right-biased monads (flash-gordon)
19
48
 
20
- [Compare v0.3.0...v0.2.1](https://github.com/dry-rb/dry-monads/compare/v0.2.1...v0.3.0)
49
+ [Compare v0.2.1...v0.3.0](https://github.com/dry-rb/dry-monads/compare/v0.2.1...v0.3.0)
21
50
 
22
51
  # v0.2.1 2016-11-13
23
52
 
@@ -30,7 +59,7 @@
30
59
  * `Right(nil).to_maybe` now returns `None` with a warning instead of failing (orisaka)
31
60
  * `Some#value_or` doesn't require an argument because `None#value_or` doesn't require it either if a block was passed (flash-gordon)
32
61
 
33
- [Compare v0.2.1...v0.2.0](https://github.com/dry-rb/dry-monads/compare/v0.2.0...v0.2.1)
62
+ [Compare v0.2.0...v0.2.1](https://github.com/dry-rb/dry-monads/compare/v0.2.0...v0.2.1)
34
63
 
35
64
  # v0.2.0 2016-09-18
36
65
 
@@ -0,0 +1,29 @@
1
+ # Issue Guidelines
2
+
3
+ ## Reporting bugs
4
+
5
+ If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
6
+
7
+ ## Reporting feature requests
8
+
9
+ Report a feature request **only after discourseing it first on [discourse.dry-rb.org](https://discourse.dry-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discourseion thread, and instead summarize what was discourseed.
10
+
11
+ ## Reporting questions, support requests, ideas, concerns etc.
12
+
13
+ **PLEASE DON'T** - use [discourse.dry-rb.org](https://discourse.dry-rb.org) instead.
14
+
15
+ # Pull Request Guidelines
16
+
17
+ A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
18
+
19
+ Other requirements:
20
+
21
+ 1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
22
+ 2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
23
+ 3) Add API documentation if it's a new feature
24
+ 4) Update API documentation if it changes an existing feature
25
+ 5) Bonus points for sending a PR to [github.com/dry-rb/dry-rb.org](github.com/dry-rb/dry-rb.org) which updates user documentation and guides
26
+
27
+ # Asking for help
28
+
29
+ If these guidelines aren't helpful, and you're stuck, please post a message on [discourse.dry-rb.org](https://discourse.dry-rb.org).
data/Gemfile CHANGED
@@ -9,5 +9,11 @@ end
9
9
 
10
10
  group :tools do
11
11
  gem 'pry-byebug', platform: :mri
12
- gem 'pry'
12
+ gem 'pry', platform: :jruby
13
+ end
14
+
15
+ group :docs do
16
+ gem 'yard'
17
+ gem 'yard-junk'
18
+ gem 'redcarpet'
13
19
  end
@@ -25,11 +25,12 @@ Gem::Specification.new do |spec|
25
25
  spec.bindir = 'exe'
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ['lib']
28
- spec.required_ruby_version = ">= 2.1.0"
28
+ spec.required_ruby_version = ">= 2.2.0"
29
29
  spec.add_dependency 'dry-equalizer'
30
- spec.add_dependency 'dry-core'
30
+ spec.add_dependency 'dry-core', '~> 0.3', '>= 0.3.3'
31
31
 
32
32
  spec.add_development_dependency 'bundler'
33
33
  spec.add_development_dependency 'rake'
34
34
  spec.add_development_dependency 'rspec'
35
+ spec.add_development_dependency 'dry-types', '>= 0.12'
35
36
  end
@@ -1,43 +1,66 @@
1
- require 'dry/monads/either'
1
+ require 'dry/core/constants'
2
2
  require 'dry/monads/maybe'
3
3
  require 'dry/monads/try'
4
4
  require 'dry/monads/list'
5
+ require 'dry/monads/result'
6
+ require 'dry/monads/result/fixed'
5
7
 
6
8
  module Dry
7
9
  # @api public
8
10
  module Monads
9
- extend self
11
+ Undefined = Dry::Core::Constants::Undefined
10
12
 
11
- # Stores the given value in one of the subtypes of {Maybe} monad.
12
- # It is essentially a wrapper for {Maybe.lift}.
13
- #
14
- # @param value [Object] the value to be stored in the monad
15
- # @return [Maybe::Some, Maybe::None]
16
- def Maybe(value)
17
- Maybe.lift(value)
18
- end
13
+ CONSTRUCTORS = [
14
+ Maybe::Mixin::Constructors,
15
+ Result::Mixin::Constructors
16
+ ].freeze
19
17
 
20
- # @param value [Object] the value to be stored in the monad
21
- # @return [Maybe::Some]
22
- def Some(value)
23
- Maybe::Some.new(value)
24
- end
18
+ Some = Maybe::Some
19
+ None = Maybe::None
20
+ Success = Result::Success
21
+ Failure = Result::Failure
25
22
 
26
- # @return [Maybe::None]
27
- def None
28
- Maybe::Some::None.instance
29
- end
23
+ extend(*CONSTRUCTORS)
24
+
25
+ def self.included(base)
26
+ super
30
27
 
31
- # @param value [Object] the value to be stored in the monad
32
- # @return [Either::Right]
33
- def Right(value)
34
- Either::Right.new(value)
28
+ base.include(*CONSTRUCTORS)
35
29
  end
36
30
 
37
- # @param value [Object] the value to be stored in the monad
38
- # @return [Either::Left]
39
- def Left(value)
40
- Either::Left.new(value)
31
+ # Creates a module that has two methods: `Success` and `Failure`.
32
+ # `Success` is identical to {Result::Mixin::Constructors#Success} and Failure
33
+ # rejects values that don't conform the value of the `error`
34
+ # parameter. This is essentially a Result type with the `Failure` part
35
+ # fixed.
36
+ #
37
+ # @example using dry-types
38
+ # module Types
39
+ # include Dry::Types.module
40
+ # end
41
+ #
42
+ # class Operation
43
+ # # :user_not_found and :account_not_found are the only
44
+ # # values allowed as failure results
45
+ # Error =
46
+ # Types.Value(:user_not_found) |
47
+ # Types.Value(:account_not_found)
48
+ #
49
+ # def find_account(id)
50
+ # account = acount_repo.find(id)
51
+ #
52
+ # account ? Success(account) : Failure(:account_not_found)
53
+ # end
54
+ #
55
+ # def find_user(id)
56
+ # # ...
57
+ # end
58
+ # end
59
+ #
60
+ # @param error [#===] the type of allowed failures
61
+ # @return [Module]
62
+ def self.Result(error, **options)
63
+ Result::Fixed[error, **options]
41
64
  end
42
65
  end
43
66
  end
@@ -1,193 +1 @@
1
- require 'dry/equalizer'
2
-
3
- require 'dry/monads/right_biased'
4
- require 'dry/monads/transformer'
5
-
6
- module Dry
7
- module Monads
8
- # Represents a value which is either correct or an error.
9
- #
10
- # @api public
11
- class Either
12
- include Dry::Equalizer(:right, :left)
13
- include Transformer
14
-
15
- attr_reader :right, :left
16
-
17
- class << self
18
- # Wraps the given value with Right
19
- #
20
- # @param value [Object] the value to be stored inside Right
21
- # @return [Either::Right]
22
- def pure(value)
23
- Right.new(value)
24
- end
25
- end
26
-
27
- # Returns self, added to keep the interface compatible with other monads.
28
- #
29
- # @return [Either::Right, Either::Left]
30
- def to_either
31
- self
32
- end
33
-
34
- # Returns the Either monad.
35
- # This is how we're doing polymorphism in Ruby 😕
36
- #
37
- # @return [Monad]
38
- def monad
39
- Either
40
- end
41
-
42
- # Represents a value that is in a correct state, i.e. everything went right.
43
- #
44
- # @api public
45
- class Right < Either
46
- include RightBiased::Right
47
-
48
- alias value right
49
-
50
- # @param right [Object] a value in a correct state
51
- def initialize(right)
52
- @right = right
53
- end
54
-
55
- # Apply the second function to value.
56
- #
57
- # @api public
58
- def either(_, f)
59
- f.call(value)
60
- end
61
-
62
- # Returns false
63
- def left?
64
- false
65
- end
66
- alias failure? left?
67
-
68
- # Returns true
69
- def right?
70
- true
71
- end
72
- alias success? right?
73
-
74
- # Does the same thing as #bind except it also wraps the value
75
- # in an instance of Either::Right monad. This allows for easier
76
- # chaining of calls.
77
- #
78
- # @example
79
- # Dry::Monads.Right(4).fmap(&:succ).fmap(->(n) { n**2 }) # => Right(25)
80
- #
81
- # @param args [Array<Object>] arguments will be transparently passed through to #bind
82
- # @return [Either::Right]
83
- def fmap(*args, &block)
84
- Right.new(bind(*args, &block))
85
- end
86
-
87
- # @return [String]
88
- def to_s
89
- "Right(#{value.inspect})"
90
- end
91
- alias inspect to_s
92
-
93
- # @return [Maybe::Some]
94
- def to_maybe
95
- Kernel.warn 'Right(nil) transformed to None' if value.nil?
96
- Dry::Monads::Maybe(value)
97
- end
98
- end
99
-
100
- # Represents a value that is in an incorrect state, i.e. something went wrong.
101
- #
102
- # @api public
103
- class Left < Either
104
- include RightBiased::Left
105
-
106
- alias value left
107
-
108
- # @param left [Object] a value in an error state
109
- def initialize(left)
110
- @left = left
111
- end
112
-
113
- # Apply the first function to value.
114
- #
115
- # @api public
116
- def either(f, _)
117
- f.call(value)
118
- end
119
-
120
- # Returns true
121
- def left?
122
- true
123
- end
124
- alias failure? left?
125
-
126
- # Returns false
127
- def right?
128
- false
129
- end
130
- alias success? right?
131
-
132
- # If a block is given passes internal value to it and returns the result,
133
- # otherwise simply returns the parameter val.
134
- #
135
- # @example
136
- # Dry::Monads.Left(ArgumentError.new('error message')).or(&:message) # => "error message"
137
- #
138
- # @param args [Array<Object>] arguments that will be passed to a block
139
- # if one was given, otherwise the first
140
- # value will be returned
141
- # @return [Object]
142
- def or(*args)
143
- if block_given?
144
- yield(value, *args)
145
- else
146
- args[0]
147
- end
148
- end
149
-
150
- # A lifted version of `#or`. Wraps the passed value or the block result with Either::Right.
151
- #
152
- # @example
153
- # Dry::Monads.Left.new('no value').or_fmap('value') # => Right("value")
154
- # Dry::Monads.Left.new('no value').or_fmap { 'value' } # => Right("value")
155
- #
156
- # @param args [Array<Object>] arguments will be passed to the underlying `#or` call
157
- # @return [Either::Right] Wrapped value
158
- def or_fmap(*args, &block)
159
- Right.new(self.or(*args, &block))
160
- end
161
-
162
- # @return [String]
163
- def to_s
164
- "Left(#{value.inspect})"
165
- end
166
- alias inspect to_s
167
-
168
- # @return [Maybe::None]
169
- def to_maybe
170
- Maybe::None.instance
171
- end
172
- end
173
-
174
- # A module that can be included for easier access to Either monads.
175
- module Mixin
176
- Right = Right
177
- Left = Left
178
-
179
- # @param value [Object] the value to be stored in the monad
180
- # @return [Either::Right]
181
- def Right(value)
182
- Right.new(value)
183
- end
184
-
185
- # @param value [Object] the value to be stored in the monad
186
- # @return [Either::Left]
187
- def Left(value)
188
- Left.new(value)
189
- end
190
- end
191
- end
192
- end
193
- end
1
+ require 'dry/monads/result'