deterministic 0.8.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +17 -0
  3. data/README.md +121 -153
  4. data/lib/deterministic/core_ext/object/result.rb +6 -0
  5. data/lib/deterministic/core_ext/{either.rb → result.rb} +2 -6
  6. data/lib/deterministic/monad.rb +3 -3
  7. data/lib/deterministic/result/chain.rb +27 -0
  8. data/lib/deterministic/result/failure.rb +5 -0
  9. data/lib/deterministic/{either → result}/match.rb +5 -5
  10. data/lib/deterministic/result/success.rb +5 -0
  11. data/lib/deterministic/{either.rb → result.rb} +29 -6
  12. data/lib/deterministic/version.rb +1 -1
  13. data/lib/deterministic.rb +5 -6
  14. data/spec/examples/bookings_spec.rb +3 -5
  15. data/spec/lib/deterministic/core_ext/object/either_spec.rb +3 -20
  16. data/spec/lib/deterministic/core_ext/result_spec.rb +22 -0
  17. data/spec/lib/deterministic/maybe_spec.rb +2 -0
  18. data/spec/lib/deterministic/monad_spec.rb +3 -3
  19. data/spec/lib/deterministic/result/chain_spec.rb +150 -0
  20. data/spec/lib/deterministic/{either → result}/failure_spec.rb +9 -6
  21. data/spec/lib/deterministic/{either → result}/match_spec.rb +5 -5
  22. data/spec/lib/deterministic/result/result_shared.rb +23 -0
  23. data/spec/lib/deterministic/{either → result}/success_spec.rb +10 -6
  24. data/spec/lib/deterministic/{either_spec.rb → result_spec.rb} +3 -3
  25. metadata +24 -27
  26. data/either.rb +0 -97
  27. data/lib/deterministic/core_ext/object/either.rb +0 -6
  28. data/lib/deterministic/either/attempt_all.rb +0 -50
  29. data/lib/deterministic/either/chain.rb +0 -22
  30. data/lib/deterministic/either/failure.rb +0 -22
  31. data/lib/deterministic/either/success.rb +0 -22
  32. data/spec/lib/deterministic/attempt_all_spec.rb +0 -115
  33. data/spec/lib/deterministic/core_ext/either_spec.rb +0 -50
  34. data/spec/lib/deterministic/either/chain_spec.rb +0 -80
  35. data/spec/lib/deterministic/either/either_shared.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e4df729f9e00305be8b4bfa828c627dd581ad07
4
- data.tar.gz: 0e1c862ea8004b24bbe65d1d86aa93946013fdad
3
+ metadata.gz: d6ccf85126958f17b98ac22932b29ed508584250
4
+ data.tar.gz: 689d36f2f3b71bcc6192129514a8ca14b2b32001
5
5
  SHA512:
6
- metadata.gz: bef331eed029917b69da1e1059b75f2d43a63ce00bac59f16e589e78de61349e57624f57bc84dac8b7011045043fae28f2fa74831b7d13fea07e2f9f90b805b9
7
- data.tar.gz: adb613df744063e6ac84bee504c2c050d70ace2add63a8b93978efbc128f84e78fee9e205c983f90de7025d7511591e802f3286a3573c314644673b640ad09b7
6
+ metadata.gz: c3c067aab6e1418a829a72505ad33f5822d3f7c749ece67aa903c306e7910ab2158cf5005f439d3dceffe032394f321109fc618c892b4324e85a2a469c8de6eb
7
+ data.tar.gz: 9500d35aedd9849fd2893534b6a220256ac71696b973e86978b4d714233a17a31acd017efdd55cd0dee18afdd25522ab05a0f357e2023819784067fecce687b4
data/HISTORY.md ADDED
@@ -0,0 +1,17 @@
1
+ ## v0.10.0
2
+ ** breaking changes **
3
+
4
+ - Remove `Either#<<`
5
+ - Rename `Either` to `Result`
6
+ - Add `Result#pipe` aka `Result#**`
7
+ - Add `Result#map` and `Result#map_err`
8
+
9
+ ## v0.9.0
10
+ ** breaking changes **
11
+
12
+ - Remove `Either.attempt_all` in favor of `Either#>>` and `Either#>=`
13
+ This greatly reduces the complexity and the code necessary.
14
+
15
+ ## 0.8.0 - v0.8.1
16
+
17
+ - Introduce `Either#>>` and `Either#>=`
data/README.md CHANGED
@@ -9,79 +9,153 @@ This is a spiritual successor of the [Monadic gem](http://github.com/pzol/monadi
9
9
 
10
10
  ## Usage
11
11
 
12
- ### Success & Failure
12
+ ### Result: Success & Failure
13
13
 
14
14
  ```ruby
15
- Success(1).to_s # => "1"
16
- Success(1) << Success(2) # => Success(2)
17
- Success(Success(1)) # => Success(1)
18
- Success(1).map { |v| v + 1} # => Success(2)
19
- Success({a:1}).to_json # => '{"Success": {"a":1}}'
20
-
21
- Failure(1).to_s # => "1"
22
- Failure(1) << Failure(2) # => Failure(1)
23
- Failure(Failure(1)) # => Failure(1)
24
- Failure(1).map { |v| v + 1} # => Failure(2)
25
- Failure({a:1}).to_json # => '{"Failure": {"a":1}}'
15
+ Success(1).to_s # => "1"
16
+ Success(Success(1)) # => Success(1)
17
+
18
+ Failure(1).to_s # => "1"
19
+ Failure(Failure(1)) # => Failure(1)
26
20
  ```
27
21
 
28
- Chaining successful actions
22
+ #### `fmap :: R a -> (a -> b) -> R b`
23
+
24
+ Maps a `Result` with the value `a` to the same `Result` with the value `b`.
29
25
 
30
26
  ```ruby
31
- Success(1).and Success(2) # => Success(2)
32
- Success(1).and_then { Success(2) } # => Success(2)
27
+ Success(1).fmap { |v| v + 1} # => Success(2)
28
+ Failure(1).fmap { |v| v - 1} # => Failure(0)
29
+ ```
33
30
 
34
- Success(1).or Success(2) # => Success(1)
35
- Success(1).or_else { Success(2) } # => Success(1)
31
+ #### `bind :: R a -> (a -> R b) -> R b`
32
+
33
+ Maps a `Result` with the value `a` to another `Result` with the value `b`.
34
+
35
+ ```ruby
36
+ Success(1).bind { |v| Failure(v + 1) } # => Failure(2)
37
+ Failure(1).fmap { |v| Success(v - 1) } # => Success(0)
38
+ ```
39
+
40
+ #### `map :: S a -> (a -> R b) -> R b`
41
+
42
+ Maps a `Success` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Success`.
43
+
44
+ ```ruby
45
+ Success(1).map { |n| n + 1 } # => Success(2)
46
+ Failure(0).map { |n| n + 1 } # => Failure(0)
47
+ ```
48
+
49
+ #### `map_err :: F a -> (a -> R b) -> R b`
50
+
51
+ Maps a `Failure` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Failure`.
52
+
53
+ ```ruby
54
+ Failure(1).map_err { |n| n + 1 } # => Success(2)
55
+ Success(0).map_err { |n| n + 1 } # => Success(0)
36
56
  ```
37
57
 
38
- Chaining failed actions
58
+ #### `try :: S a -> ( a -> R b) -> R b`
59
+
60
+ Just like `#map`, transforms `a` to another `Result`, but it will also catch raised exceptions and wrap them with a `Failure`.
61
+
62
+ ```ruby
63
+ Success(0).try { |n| raise "Error" } # => Failure(Error)
64
+ ```
65
+
66
+ #### `and :: S a -> R b -> R b`
67
+
68
+ Replaces `Success a` with `Result b`. If a `Failure` is passed as argument, it is ignored.
39
69
 
40
70
  ```ruby
71
+ Success(1).and Success(2) # => Success(2)
41
72
  Failure(1).and Success(2) # => Failure(1)
73
+ ```
74
+
75
+ #### `and_then :: S a -> (a -> R b) -> R b`
76
+
77
+ Replaces `Success a` with the result of the block. If a `Failure` is passed as argument, it is ignored.
78
+
79
+ ```ruby
80
+ Success(1).and_then { Success(2) } # => Success(2)
42
81
  Failure(1).and_then { Success(2) } # => Failure(1)
82
+ ```
83
+
84
+ #### `or :: F a -> R b -> R b`
85
+ Replaces `Failure a` with `Result`. If a `Failure` is passed as argument, it is ignored.
43
86
 
87
+ ```ruby
88
+ Success(1).or Success(2) # => Success(1)
44
89
  Failure(1).or Success(1) # => Success(1)
45
- Failure(1).or_else { |v| Success(v)} # => Success(1)
46
90
  ```
47
91
 
48
- The value or block result must always be a `Success` or `Failure`
92
+ #### `or_else :: F a -> (a -> R b) -> R b`
93
+
94
+ Replaces `Failure a` with the result of the block. If a `Success` is passed as argument, it is ignored.
95
+
96
+ ```ruby
97
+ Success(1).or_else { Success(2) } # => Success(1)
98
+ Failure(1).or_else { |n| Success(n)} # => Success(1)
99
+ ```
100
+
101
+ #### `pipe :: R a -> (R a -> b) -> R a`
102
+
103
+ Executes the block passed, but completely ignores its result. If an error is raised within the block it will **NOT** be catched.
104
+
105
+ ```ruby
106
+ Success(1).try { |n| log(n.value) } # => Success(1)
107
+ ```
108
+
109
+ The value or block result must always be a `Result` i.e. `Success` or `Failure`.
110
+
111
+ ### Result Chaining
49
112
 
50
- ### Either.chain
51
113
  You can easily chain the execution of several operations. Here we got some nice function composition.
52
114
  The method must be a unary function, i.e. it always takes one parameter - the context, which is passed from call to call.
53
115
 
116
+ The following aliases are defined
117
+
118
+ ```ruby
119
+ alias :>> :map
120
+ alias :>= :try
121
+ alias :** :pipe # the operator must be right associative
122
+ ```
123
+
124
+ This allows the composition of procs or lambdas and thus allow a clear definiton of a pipeline.
125
+
126
+ ```ruby
127
+ Success(params) >> validate >> build_request ** log >> send ** log >> build_response
128
+ ```
129
+
130
+ #### Complex Example in a Builder Class
131
+
54
132
  ```ruby
55
133
  class Foo
56
134
  include Deterministic
57
- alias :m :method
135
+ alias :m :method # method conveniently returns a Proc to a method
58
136
 
59
- def call
60
- setup >> m(:validate) >> m(:send)
137
+ def call(params)
138
+ Success(params) >> m(:validate) >> m(:send)
61
139
  end
62
140
 
63
- def setup
64
- Success(1)
65
- end
66
-
67
- def validate(ctx)
141
+ def validate(params)
68
142
  # do stuff
69
- Success(ctx + 1)
143
+ Success(validate_and_cleansed_params)
70
144
  end
71
145
 
72
- def send(ctx)
146
+ def send(clean_params)
73
147
  # do stuff
74
- Success(ctx + 1)
148
+ Success(result)
75
149
  end
76
150
  end
77
151
 
78
152
  Foo.new.call # Success(3)
79
153
  ```
80
154
 
81
- Chaining works with blocks (`#chain` is an alias for `#>>`)
155
+ Chaining works with blocks (`#map` is an alias for `#>>`)
82
156
 
83
157
  ```ruby
84
- Success(1).chain {|ctx| Success(ctx + 1)}
158
+ Success(1).map {|ctx| Success(ctx + 1)}
85
159
  ```
86
160
 
87
161
  it also works with lambdas
@@ -107,75 +181,21 @@ end
107
181
  Success(0) >> method(:works) >> method(:breaks) >> method(:never_executed) # Failure(2)
108
182
  ```
109
183
 
110
- `#chain` aka `#>>` will not catch any exceptions raised. If you want automatic exception handling, the `#try` aka `#>=` will catch an error and wrap it with a failure
184
+ `#map` aka `#>>` will not catch any exceptions raised. If you want automatic exception handling, the `#try` aka `#>=` will catch an error and wrap it with a failure
111
185
 
112
186
  ```ruby
113
187
  def error(ctx)
114
- raise "error #{1}"
188
+ raise "error #{ctx}"
115
189
  end
116
190
 
117
191
  Success(1) >= method(:error) # Failure(RuntimeError(error 1))
118
192
  ```
119
193
 
120
- ### Either.attempt_all
121
- The basic idea is to execute a chain of units of work and make sure all return either `Success` or `Failure`.
122
- This remains for compatibility reasons, personally I would use the `>>` chaining.
123
-
124
-
125
- ```ruby
126
- Either.attempt_all do
127
- try { 1 }
128
- try { |prev| prev + 1 }
129
- end # => Success(2)
130
- ```
131
- Take notice, that the result of of unit of work will be passed to the next one. So the result of prepare_somehing will be something in the second try.
132
-
133
- If any of the units of work in between fail, the rest will not be executed and the last `Failure` will be returned.
134
-
135
- ```ruby
136
- Either.attempt_all do
137
- try { 1 }
138
- try { raise "error" }
139
- try { 2 }
140
- end # => Failure(RuntimeError("error"))
141
- ```
142
-
143
- However, the real fun starts if you use it with your own context. You can use this as a state container (meh!) or to pass a dependency locator:
144
-
145
- ```ruby
146
- class Context
147
- attr_accessor :env, :settings
148
- def some_service
149
- end
150
- end
151
-
152
- # exemplary unit of work
153
- module LoadSettings
154
- def self.call(env)
155
- settings = load(env)
156
- settings.nil? ? Failure('could not load settings') : Success(settings)
157
- end
158
-
159
- def load(env)
160
- end
161
- end
162
-
163
- Either.attempt_all(context) do
164
- # this unit of work explicitly returns success or failure
165
- # no exceptions are catched and if they occur, well, they behave as expected
166
- # methods from the context can be accessed, the use of self for setters is necessary
167
- let { self.settings = LoadSettings.call(env) }
168
-
169
- # with #try all exceptions will be transformed into a Failure
170
- try { do_something }
171
- end
172
- ```
173
-
174
194
  ### Pattern matching
175
195
  Now that you have some result, you want to control flow by providing patterns.
176
196
  `#match` can match by
177
197
 
178
- * success, failure, either or any
198
+ * success, failure, result or any
179
199
  * values
180
200
  * lambdas
181
201
  * classes
@@ -184,7 +204,7 @@ Now that you have some result, you want to control flow by providing patterns.
184
204
  Success(1).match do
185
205
  success { |v| "success #{v}"}
186
206
  failure { |v| "failure #{v}"}
187
- either { |v| "either #{v}"}
207
+ result { |v| "result #{v}"}
188
208
  end # => "success 1"
189
209
  ```
190
210
  Note1: the inner value has been unwrapped!
@@ -217,18 +237,6 @@ Success([1, 2, 3]).match do
217
237
  end # => 1
218
238
  ```
219
239
 
220
- Combining `#attempt_all` and `#match` is the ultimate sophistication:
221
-
222
- ```ruby
223
- Either.attempt_all do
224
- try { 1 }
225
- try { |v| v + 1 }
226
- end.match do
227
- success(1) { |v| "We made it to step #{v}" }
228
- success(2) { |v| "The correct answer is #{v}"}
229
- end # => "The correct answer is 2"
230
- ```
231
-
232
240
  If no match was found a `NoMatchError` is raised, so make sure you always cover all possible outcomes.
233
241
 
234
242
  ```ruby
@@ -246,59 +254,19 @@ end # => "catch-all"
246
254
  ```
247
255
 
248
256
  ## core_ext
249
- You can use a core extension, to include Either in your own class or in Object, i.e. in all classes.
257
+ You can use a core extension, to include Result in your own class or in Object, i.e. in all classes.
250
258
 
251
- In a class, as a mixin
259
+ ## Result
252
260
 
253
261
  ```ruby
254
- require "deterministic/core_ext/either" # this includes Deterministic in the global namespace!
255
- class UnderTest
256
- include Deterministic::CoreExt::Either
257
- def test
258
- attempt_all do
259
- try { foo }
260
- end
261
- end
262
-
263
- def foo
264
- 1
265
- end
266
- end
262
+ require 'deterministic/core_ext/object/result'
267
263
 
268
- ut = UnderTest.new
269
- ut.test # => Success(1)
264
+ [1].success? # => false
265
+ Success(1).failure? # => false
266
+ Success(1).success? # => true
267
+ Failure(1).result? # => true
270
268
  ```
271
269
 
272
- To add it to all classes
273
-
274
- ```ruby
275
- require "deterministic/core_ext/object/either" # this includes Deterministic to Object
276
-
277
- class UnderTest
278
- def test
279
- attempt_all do
280
- try { foo }
281
- end
282
- end
283
-
284
- def foo
285
- 1
286
- end
287
- end
288
-
289
- ut = UnderTest.new
290
- ut.test # => Success(1)
291
- ```
292
-
293
- or use it on built-in classes
294
-
295
- ```ruby
296
- require "deterministic/core_ext/object/either"
297
- h = {a:1}
298
- h.attempt_all do
299
- try { |s| s[:a] + 1}
300
- end # => Success(2)
301
- ```
302
270
 
303
271
  ## Maybe
304
272
  The simplest NullObject wrapper there can be. It adds `#some?` and `#none?` to `Object` though.
@@ -307,7 +275,7 @@ The simplest NullObject wrapper there can be. It adds `#some?` and `#none?` to `
307
275
  require 'deterministic/maybe' # you need to do this explicitly
308
276
  Maybe(nil).foo # => None
309
277
  Maybe(nil).foo.bar # => None
310
- Mmaybe({a: 1})[:a] # => 1
278
+ Maybe({a: 1})[:a] # => 1
311
279
 
312
280
  Maybe(nil).none? # => true
313
281
  Maybe({}).none? # => false
@@ -332,7 +300,7 @@ null.foo # => NoMethodError
332
300
 
333
301
  ## Inspirations
334
302
  * My [Monadic gem](http://github.com/pzol/monadic) of course
335
- * `#attempt_all` was somewhat inspired by [An error monad in Clojure](http://brehaut.net/blog/2011/error_monads)
303
+ * `#attempt_all` was somewhat inspired by [An error monad in Clojure](http://brehaut.net/blog/2011/error_monads) (attempt all has now been removed)
336
304
  * [Pithyless' rumblings](https://gist.github.com/pithyless/2216519)
337
305
  * [either by rsslldnphy](https://github.com/rsslldnphy/either)
338
306
  * [Functors, Applicatives, And Monads In Pictures](http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html)
@@ -0,0 +1,6 @@
1
+ require "deterministic/core_ext/result"
2
+
3
+ include Deterministic
4
+ class Object
5
+ include Deterministic::CoreExt::Result
6
+ end
@@ -2,7 +2,7 @@ include Deterministic
2
2
 
3
3
  module Deterministic
4
4
  module CoreExt
5
- module Either
5
+ module Result
6
6
  def success?
7
7
  self.is_a? Success
8
8
  end
@@ -11,13 +11,9 @@ module Deterministic
11
11
  self.is_a? Failure
12
12
  end
13
13
 
14
- def either?
14
+ def result?
15
15
  success? || failure?
16
16
  end
17
-
18
- def attempt_all(context=self, &block)
19
- Deterministic::Either::AttemptAll.new(context, &block).call(self)
20
- end
21
17
  end
22
18
  end
23
19
  end
@@ -16,17 +16,17 @@ module Deterministic
16
16
  # The functor: takes a function (a -> b) and applies it to the inner value of the monad (Ma),
17
17
  # boxes it back to the same monad (Mb)
18
18
  # fmap :: (a -> b) -> M a -> M b
19
- def map(proc=nil, &block)
19
+ def fmap(proc=nil, &block)
20
20
  result = (proc || block).call(value)
21
21
  self.class.new(result)
22
22
  end
23
23
 
24
24
  # The monad: takes a function which returns a monad (of the same type), applies the function
25
- # bind :: M a -> (a -> Mb) -> M b
25
+ # bind :: (a -> Mb) -> M a -> M b
26
26
  # the self.class, i.e. the containing monad is passed as a second (optional) arg to the function
27
27
  def bind(proc=nil, &block)
28
28
  (proc || block).call(value, self.class).tap do |result|
29
- raise NotMonadError, "Expected #{result.inspect} to be an Either" unless result.is_a? self.class
29
+ raise NotMonadError, "Expected #{result.inspect} to be an Result" unless result.is_a? self.class
30
30
  end
31
31
  end
32
32
  alias :'>>=' :bind
@@ -0,0 +1,27 @@
1
+ module Deterministic
2
+ class Result
3
+ module Chain
4
+ def map(proc=nil, &block)
5
+ return self if failure?
6
+ bind(proc || block)
7
+ end
8
+
9
+ alias :>> :map
10
+
11
+ def map_err(proc=nil, &block)
12
+ return self if success?
13
+ bind(proc || block)
14
+ end
15
+
16
+ def try(proc=nil, &block)
17
+ map(proc, &block)
18
+ rescue => err
19
+ Failure(err)
20
+ end
21
+
22
+ alias :>= :try
23
+
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,5 @@
1
+ module Deterministic
2
+ class Failure < Result
3
+ class << self; public :new; end
4
+ end
5
+ end
@@ -4,7 +4,7 @@ module Deterministic::PatternMatching
4
4
  context ||= block.binding.eval('self')
5
5
  match = Match.new(self, context)
6
6
  match.instance_eval &block
7
- match.result
7
+ match.call
8
8
  end
9
9
 
10
10
  class NoMatchError < StandardError; end
@@ -16,14 +16,14 @@ module Deterministic::PatternMatching
16
16
  @collection = []
17
17
  end
18
18
 
19
- def result
19
+ def call
20
20
  matcher = @collection.detect { |m| m.matches?(@container.value) }
21
- raise NoMatchError, "No could be made for #{@container}" if matcher.nil?
21
+ raise NoMatchError, "No match could be made for #{@container.inspect}" if matcher.nil?
22
22
  @context.instance_exec(@container.value, &matcher.block)
23
23
  end
24
24
 
25
- # TODO: Either specific DSL, will need to move it to Either, later on
26
- %w[Success Failure Either].each do |s|
25
+ # TODO: Result specific DSL, will need to move it to Result, later on
26
+ %w[Success Failure Result].each do |s|
27
27
  define_method s.downcase.to_sym do |value=nil, &block|
28
28
  klas = Module.const_get(s)
29
29
  push(klas, value, block)
@@ -0,0 +1,5 @@
1
+ module Deterministic
2
+ class Success < Result
3
+ class << self; public :new; end
4
+ end
5
+ end
@@ -1,13 +1,13 @@
1
1
  module Deterministic
2
2
  # Abstract parent of Success and Failure
3
- class Either
3
+ class Result
4
4
  include Monad
5
5
  include Deterministic::PatternMatching
6
6
  include Chain
7
7
 
8
8
  def bind(proc=nil, &block)
9
- (proc || block).call(value, self.class).tap do |result|
10
- raise NotMonadError, "Expected #{result.inspect} to be an Either" unless result.is_a? self.class.superclass
9
+ (proc || block).call(value).tap do |result|
10
+ raise NotMonadError, "Expected #{result.inspect} to be an Result" unless result.is_a? self.class.superclass
11
11
  end
12
12
  end
13
13
 
@@ -19,9 +19,33 @@ module Deterministic
19
19
  is_a? Failure
20
20
  end
21
21
 
22
- def <<(other)
22
+ def pipe(proc=nil, &block)
23
+ (proc || block).call(self)
24
+ self
25
+ end
26
+
27
+ alias :** :pipe
28
+
29
+ def and(other)
30
+ return self if failure?
31
+ raise NotMonadError, "Expected #{other.inspect} to be an Result" unless other.is_a? Result
32
+ other
33
+ end
34
+
35
+ def and_then(&block)
23
36
  return self if failure?
24
- return other if other.is_a? Either
37
+ bind(&block)
38
+ end
39
+
40
+ def or(other)
41
+ return self if success?
42
+ raise NotMonadError, "Expected #{other.inspect} to be an Result" unless other.is_a? Result
43
+ return other
44
+ end
45
+
46
+ def or_else(&block)
47
+ return self if success?
48
+ bind(&block)
25
49
  end
26
50
 
27
51
  # This is an abstract class, can't ever instantiate it directly
@@ -40,7 +64,6 @@ module Deterministic
40
64
  end
41
65
 
42
66
  module_function
43
-
44
67
  def Success(value)
45
68
  Success.new(value)
46
69
  end
@@ -1,3 +1,3 @@
1
1
  module Deterministic
2
- VERSION = "0.8.1"
2
+ VERSION = "0.10.0"
3
3
  end
data/lib/deterministic.rb CHANGED
@@ -5,10 +5,9 @@ warn "WARN: Deterministic is meant to run on Ruby 2+" if RUBY_VERSION.to_f < 2
5
5
  module Deterministic; end
6
6
 
7
7
  require 'deterministic/monad'
8
- require 'deterministic/either/match'
9
- require 'deterministic/either/chain'
10
- require 'deterministic/either'
11
- require 'deterministic/either/attempt_all'
12
- require 'deterministic/either/success'
13
- require 'deterministic/either/failure'
8
+ require 'deterministic/result/match'
9
+ require 'deterministic/result/chain'
10
+ require 'deterministic/result'
11
+ require 'deterministic/result/success'
12
+ require 'deterministic/result/failure'
14
13
  require 'deterministic/none'
@@ -33,10 +33,8 @@ module Examples
33
33
  end
34
34
 
35
35
  def call(dirty_params)
36
- result = Either.attempt_all(self) do
37
- try { parse_params(dirty_params) }
38
- let { |params| read_bookings(params) }
39
- end.match(world) do
36
+
37
+ ( parse_params(dirty_params) >> method(:read_bookings) ).match(world) do
40
38
  success(Array) { |bookings| booking_list(bookings) }
41
39
  success { |booking| booking(booking) }
42
40
  failure(:no_bookings) { empty_booking_list }
@@ -49,7 +47,7 @@ module Examples
49
47
  attr_reader :bookings_repo, :world
50
48
 
51
49
  def parse_params(dirty_params)
52
- dirty_params
50
+ Success(dirty_params)
53
51
  end
54
52
 
55
53
  def read_bookings(params)
@@ -1,28 +1,11 @@
1
1
  require "spec_helper"
2
- require "deterministic/core_ext/object/either"
2
+ require "deterministic/core_ext/object/result"
3
3
 
4
- describe Deterministic::CoreExt::Either, "object", isolate: true do
4
+ describe Deterministic::CoreExt::Result, "object", isolate: true do
5
5
  it "does something" do
6
6
  h = {a: 1}
7
7
  expect(h.success?).to be_falsey
8
8
  expect(h.failure?).to be_falsey
9
- expect(h.either?).to be_falsey
10
- end
11
-
12
- it "use attempt_all in an instance" do
13
- class UnderTest
14
- def test
15
- attempt_all do
16
- try { foo }
17
- end
18
- end
19
-
20
- def foo
21
- 1
22
- end
23
- end
24
-
25
- ut = UnderTest.new
26
- expect(ut.test).to eq Success(1)
9
+ expect(h.result?).to be_falsey
27
10
  end
28
11
  end