deterministic 0.12.1 → 0.13.1

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: 3c142a92639ccc4051cc59535565f1acb5816a25
4
- data.tar.gz: c916f4398175f4a5a0d3fc2142263d9c999d7ac8
3
+ metadata.gz: 120b61f2caf3653ca63fc4bca59908c8c3add91b
4
+ data.tar.gz: 2813dd0b90f301a5afcbc7861e446c3bdc507f15
5
5
  SHA512:
6
- metadata.gz: 5da47c489e0c973dfb02aa9d3f1a968b812855b3af4001f8c70ea72aa5ed8188a587713bf13df63b9af0dfadbd5f4420c93b90592e8442997e21dc9590b7b2a3
7
- data.tar.gz: c7252b32ba1889a08a32c05aadb0c76469822f2a646f1bb1f54bf54a6e7c081c3e43640a57e66b68da0c6d88da5092638ac7a19de1fb56a397de741d72d3057d
6
+ metadata.gz: d3195c0fbd1f114843e7003e84b9e24ba129933986ef948f44f19be83202719148b44554d27146acd0addd728aab98bb265356ea1d14e8338b8eaee705bdd91e
7
+ data.tar.gz: 721194e06a0618864efffcf079f6cc4220c58b3e0a962e7f2c43186d01e2bcc8825d34999c7c8a4abe8270bd6153901d30dd46393f7e8327a14bdb640a95f094
data/HISTORY.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## v0.13.0
2
+
3
+ - Add `Option#value_to_a`
4
+ - Add `Option#+`
5
+ - Make `None` a real monad (little impact on the real world)
6
+ - Add `Either`
7
+ - Add `Option#value_or`
8
+ - `None#value` is now private
9
+
10
+ ## v0.12.1
11
+
12
+ - Fix backwards compatibility with Ruby < 2.0.0
13
+
14
+ ## v0.12.0
15
+
16
+ - Add Option
17
+ - Nest `Success` and `Failure` under `Result`
18
+
1
19
  ## v0.10.0
2
20
  ** breaking changes **
3
21
 
data/README.md CHANGED
@@ -6,6 +6,29 @@ Deterministic is to help your code to be more confident, it's specialty is flow
6
6
 
7
7
  This is a spiritual successor of the [Monadic gem](http://github.com/pzol/monadic). The goal of the rewrite is to get away from a bit to forceful aproach I took in Monadic, especially when it comes to coercing monads, but also a more practical but at the same time more strict adherence to monad laws.
8
8
 
9
+ ## Patterns
10
+
11
+ Deterministic provides different monads, here is a short guide, when to use which
12
+
13
+ #### Result: Success & Failure
14
+ - an operation which can succeed or fail
15
+ - the result (content) of of the success or failure is important
16
+ - you are building one thing
17
+ - chaining: if one fails (Failure), don't execute the rest
18
+
19
+ #### Option: Some & None
20
+ - an operation which returns either some result or nothing
21
+ - in case it returns nothing it is not important to know why
22
+ - you are working rather with a collection of things
23
+ - chaining: execute all and then select the successful ones (Some)
24
+
25
+ #### Either: Left & Right
26
+ - an operation which returns several good and bad results
27
+ - the results of both are important
28
+ - chaining: if one fails, continue, the content of the failed and successful are important
29
+
30
+ #### Maybe
31
+ - an object may be nil, you want to avoid endless nil? checks
9
32
 
10
33
  ## Usage
11
34
 
@@ -19,8 +42,6 @@ Failure(1).to_s # => "1"
19
42
  Failure(Failure(1)) # => Failure(1)
20
43
  ```
21
44
 
22
- #### `fmap(self: Result(a), op: |a| -> b) -> Result(b)`
23
-
24
45
  Maps a `Result` with the value `a` to the same `Result` with the value `b`.
25
46
 
26
47
  ```ruby
@@ -28,82 +49,62 @@ Success(1).fmap { |v| v + 1} # => Success(2)
28
49
  Failure(1).fmap { |v| v - 1} # => Failure(0)
29
50
  ```
30
51
 
31
- #### `bind(self: Result(a), op: |a| -> Result(b)) -> Result(b)`
32
-
33
52
  Maps a `Result` with the value `a` to another `Result` with the value `b`.
34
53
 
35
54
  ```ruby
36
55
  Success(1).bind { |v| Failure(v + 1) } # => Failure(2)
37
- Failure(1).fmap { |v| Success(v - 1) } # => Success(0)
56
+ Failure(1).bind { |v| Success(v - 1) } # => Success(0)
38
57
  ```
39
58
 
40
- #### `map(self: Success(a), op: |a| -> Result(b)) -> Result(b)`
41
-
42
59
  Maps a `Success` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Success`.
43
60
 
44
61
  ```ruby
45
62
  Success(1).map { |n| n + 1 } # => Success(2)
46
63
  Failure(0).map { |n| n + 1 } # => Failure(0)
47
64
  ```
48
-
49
- #### `map_err(self: Failure(a), op: |a| -> Result(b)) -> Result(b)`
50
-
51
65
  Maps a `Failure` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Failure`.
52
66
 
53
67
  ```ruby
54
- Failure(1).map_err { |n| n + 1 } # => Success(2)
55
- Success(0).map_err { |n| n + 1 } # => Success(0)
68
+ Failure(1).map_err { |n| n + 1 } # => Success(2)
69
+ Success(0).map_err { |n| n + 1 } # => Success(0)
56
70
  ```
57
71
 
58
- #### `try(self: Success(a), op: |a| -> Result(b)) -> Result(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
72
  ```ruby
63
73
  Success(0).try { |n| raise "Error" } # => Failure(Error)
64
74
  ```
65
75
 
66
- #### `and(self: Success(a), other: Result(b)) -> Result(b)`
67
-
68
76
  Replaces `Success a` with `Result b`. If a `Failure` is passed as argument, it is ignored.
69
77
 
70
78
  ```ruby
71
- Success(1).and Success(2) # => Success(2)
72
- Failure(1).and Success(2) # => Failure(1)
79
+ Success(1).and Success(2) # => Success(2)
80
+ Failure(1).and Success(2) # => Failure(1)
73
81
  ```
74
82
 
75
- #### `and_then(self: Success(a), op: |a| -> Result(b)) -> Result(b)`
76
-
77
83
  Replaces `Success a` with the result of the block. If a `Failure` is passed as argument, it is ignored.
78
84
 
79
85
  ```ruby
80
- Success(1).and_then { Success(2) } # => Success(2)
81
- Failure(1).and_then { Success(2) } # => Failure(1)
86
+ Success(1).and_then { Success(2) } # => Success(2)
87
+ Failure(1).and_then { Success(2) } # => Failure(1)
82
88
  ```
83
89
 
84
- #### `or(self: Failure(a), other: Result(b)) -> Result(b)`
85
90
  Replaces `Failure a` with `Result`. If a `Failure` is passed as argument, it is ignored.
86
91
 
87
92
  ```ruby
88
- Success(1).or Success(2) # => Success(1)
89
- Failure(1).or Success(1) # => Success(1)
93
+ Success(1).or Success(2) # => Success(1)
94
+ Failure(1).or Success(1) # => Success(1)
90
95
  ```
91
96
 
92
- #### `or_else(self: Failure(a), op: |a| -> Result(b)) -> Result(b)`
93
-
94
97
  Replaces `Failure a` with the result of the block. If a `Success` is passed as argument, it is ignored.
95
98
 
96
99
  ```ruby
97
- Success(1).or_else { Success(2) } # => Success(1)
98
- Failure(1).or_else { |n| Success(n)} # => Success(1)
100
+ Success(1).or_else { Success(2) } # => Success(1)
101
+ Failure(1).or_else { |n| Success(n)} # => Success(1)
99
102
  ```
100
103
 
101
- #### `pipe(self: Result(a), op: |Result(a)| -> b) -> Result(a)`
102
-
103
104
  Executes the block passed, but completely ignores its result. If an error is raised within the block it will **NOT** be catched.
104
105
 
105
106
  ```ruby
106
- Success(1).try { |n| log(n.value) } # => Success(1)
107
+ Success(1).try { |n| log(n.value) } # => Success(1)
107
108
  ```
108
109
 
109
110
  The value or block result must always be a `Result` i.e. `Success` or `Failure`.
@@ -256,7 +257,7 @@ end # => "catch-all"
256
257
  ## core_ext
257
258
  You can use a core extension, to include Result in your own class or in Object, i.e. in all classes.
258
259
 
259
- ## Result
260
+
260
261
 
261
262
  ```ruby
262
263
  require 'deterministic/core_ext/object/result'
@@ -267,6 +268,62 @@ Success(1).success? # => true
267
268
  Failure(1).result? # => true
268
269
  ```
269
270
 
271
+ ## Option
272
+
273
+ ```ruby
274
+ Some(1).some? # #=> true
275
+ Some(1).none? # #=> false
276
+ None.some? # #=> false
277
+ None.none? # #=> true
278
+
279
+ Some(1).fmap { |n| n + 1 } # => Some(2)
280
+ None.fmap { |n| n + 1 } # => None
281
+
282
+ Some(1).map { |n| Some(n + 1) } # => Some(2)
283
+ Some(1).map { |n| None } # => None
284
+ None.map { |n| Some(n + 1) } # => None
285
+
286
+ Some(1).value # => 1
287
+ Some(1).value_or(2) # => 1
288
+ None.value # => NoMethodError
289
+ None.value_or(0) # => 0
290
+
291
+ Some(1).value_to_a # => Some([1])
292
+ Some([1]).value_to_a # => Some([1])
293
+ None.value_to_a # => None
294
+
295
+ Some(1) + Some(1) # => Some(2)
296
+ Some([1]) + Some(1) # => TypeError: No implicit conversion
297
+ None + Some(1) # => Some(1)
298
+ Some(1) + None # => Some(1)
299
+ Some([1]) + None + Some([2]) # => Some([1, 2])
300
+ ```
301
+
302
+ ### Coercion
303
+ ```ruby
304
+ Option.any?(nil) # => None
305
+ Option.any?([]) # => None
306
+ Option.any?({}) # => None
307
+ Option.any?(1) # => Some(1)
308
+
309
+ Option.some?(nil) # => None
310
+ Option.some?([]) # => Some([])
311
+ Option.some?({}) # => Some({})
312
+ Option.some?(1) # => Some(1)
313
+
314
+ Option.try! { 1 } # => Some(1)
315
+ Option.try! { raise "error"} # => None
316
+ ```
317
+
318
+ ### Pattern Matching
319
+ ```ruby
320
+ Some(1).match {
321
+ some(1) { |n| n + 1 }
322
+ some { 1 }
323
+ none { 0 }
324
+ } # => 2
325
+ ```
326
+
270
327
 
271
328
  ## Maybe
272
329
  The simplest NullObject wrapper there can be. It adds `#some?` and `#null?` to `Object` though.
@@ -0,0 +1,35 @@
1
+ module Deterministic
2
+ class Either
3
+ include Monad
4
+ class << self
5
+ public :new
6
+ end
7
+
8
+ def initialize(left=[], right=[])
9
+ @left, @right = left, right
10
+ end
11
+
12
+ attr_reader :left, :right
13
+
14
+ def +(other)
15
+ raise Deterministic::Monad::NotMonadError, "Expected an Either, got #{other.class}" unless other.is_a? Either
16
+
17
+ Either.new(left + other.left, right + other.right)
18
+ end
19
+
20
+ undef :value
21
+
22
+ def inspect
23
+ "Either(left: #{left.inspect}, right: #{right.inspect})"
24
+ end
25
+
26
+ end
27
+ module_function
28
+ def Left(value)
29
+ Either.new(Array[value], [])
30
+ end
31
+
32
+ def Right(value)
33
+ Either.new([], Array[value])
34
+ end
35
+ end
@@ -18,9 +18,10 @@ module Deterministic
18
18
  end
19
19
 
20
20
  def call
21
- matcher = @collection.detect { |m| m.matches?(@container.value) }
21
+ value = @container.respond_to?(:value) ? @container.value : nil
22
+ matcher = @collection.detect { |m| m.matches?(value) }
22
23
  raise NoMatchError, "No match could be made for #{@container.inspect}" if matcher.nil?
23
- @context.instance_exec(@container.value, &matcher.block)
24
+ @context.instance_exec(value, &matcher.block)
24
25
  end
25
26
 
26
27
  # catch-all
@@ -2,6 +2,7 @@ module Deterministic
2
2
  module Monad
3
3
  class NotMonadError < StandardError; end
4
4
 
5
+ # Basicly the `pure` function
5
6
  def initialize(value)
6
7
  @value = join(value)
7
8
  end
@@ -45,6 +45,22 @@ module Deterministic
45
45
  bind(proc || block)
46
46
  end
47
47
 
48
+ ## Convert the inner value to an Array
49
+ def value_to_a
50
+ map { self.class.new(Array(value)) }
51
+ end
52
+
53
+ ## Add the inner values of two Some
54
+ def +(other)
55
+ return other if none?
56
+ fmap { |v|
57
+ other.match {
58
+ some { v + other.value }
59
+ none { self }
60
+ }
61
+ }
62
+ end
63
+
48
64
  def some?
49
65
  is_a? Some
50
66
  end
@@ -53,35 +69,36 @@ module Deterministic
53
69
  is_a? None
54
70
  end
55
71
 
72
+ def value_or(default)
73
+ return default if none?
74
+ return value
75
+ end
76
+
56
77
  class Some < Option
57
78
  class << self; public :new; end
58
79
  end
59
80
 
60
81
  class None < Option
61
82
  class << self; public :new; end
62
- def initialize(*args); end
83
+ def initialize(*args)
84
+ @value = self
85
+ end
63
86
 
64
87
  def inspect
65
88
  "None"
66
89
  end
67
90
 
68
- # def value
69
- # self
70
- # end
71
- def none(*args)
91
+ private :value
92
+
93
+ def fmap(*args)
72
94
  self
73
95
  end
74
96
 
75
- alias :fmap :none
76
- alias :map :none
97
+ alias :map :fmap
77
98
 
78
99
  def ==(other)
79
100
  other.class == self.class
80
101
  end
81
-
82
- # def value
83
- # self # raise "value called on a None"
84
- # end
85
102
  end
86
103
  end
87
104
 
@@ -18,7 +18,11 @@ module Deterministic
18
18
  end
19
19
 
20
20
  include PatternMatching
21
- include Chain
21
+
22
+ # This is an abstract class, can't ever instantiate it directly
23
+ class << self
24
+ protected :new
25
+ end
22
26
 
23
27
  def success?
24
28
  is_a? Success
@@ -28,6 +32,8 @@ module Deterministic
28
32
  is_a? Failure
29
33
  end
30
34
 
35
+ # `pipe(self: Result(a), op: |Result(a)| -> b) -> Result(a)`
36
+ # Executes the block passed, but completely ignores its result. If an error is raised within the block it will **NOT** be catched.
31
37
  def pipe(proc=nil, &block)
32
38
  (proc || block).call(self)
33
39
  self
@@ -35,32 +41,61 @@ module Deterministic
35
41
 
36
42
  alias :** :pipe
37
43
 
44
+ # `pipe(self: Result(a), op: |Result(a)| -> b) -> Result(a)`
45
+ # Replaces `Success a` with `Result b`. If a `Failure` is passed as argument, it is ignored.
38
46
  def and(other)
39
47
  return self if failure?
40
48
  raise NotMonadError, "Expected #{other.inspect} to be an Result" unless other.is_a? Result
41
49
  other
42
50
  end
43
51
 
52
+ # `and_then(self: Success(a), op: |a| -> Result(b)) -> Result(b)`
53
+ # Replaces `Success a` with the result of the block. If a `Failure` is passed as argument, it is ignored.
44
54
  def and_then(&block)
45
55
  return self if failure?
46
56
  bind(&block)
47
57
  end
48
58
 
59
+ # `or(self: Failure(a), other: Result(b)) -> Result(b)`
60
+ # Replaces `Failure a` with `Result`. If a `Failure` is passed as argument, it is ignored.
49
61
  def or(other)
50
62
  return self if success?
51
63
  raise NotMonadError, "Expected #{other.inspect} to be an Result" unless other.is_a? Result
52
64
  return other
53
65
  end
54
66
 
67
+ # `or_else(self: Failure(a), op: |a| -> Result(b)) -> Result(b)`
68
+ # Replaces `Failure a` with the result of the block. If a `Success` is passed as argument, it is ignored.
55
69
  def or_else(&block)
56
70
  return self if success?
57
71
  bind(&block)
58
72
  end
59
73
 
60
- # This is an abstract class, can't ever instantiate it directly
61
- class << self
62
- protected :new
74
+ # `map(self: Success(a), op: |a| -> Result(b)) -> Result(b)`
75
+ # Maps a `Success` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Success`.
76
+ def map(proc=nil, &block)
77
+ return self if failure?
78
+ bind(proc || block)
79
+ end
80
+
81
+ alias :>> :map
82
+
83
+ # `map_err(self: Failure(a), op: |a| -> Result(b)) -> Result(b)`
84
+ # Maps a `Failure` with the value `a` to another `Result` with the value `b`. It works like `#bind` but only on `Failure`.
85
+ def map_err(proc=nil, &block)
86
+ return self if success?
87
+ bind(proc || block)
88
+ end
89
+
90
+ # `pipe(self: Result(a), op: |Result(a)| -> b) -> Result(a)`
91
+ # Executes the block passed, but completely ignores its result. If an error is raised within the block it will **NOT** be catched.
92
+ def try(proc=nil, &block)
93
+ map(proc, &block)
94
+ rescue => err
95
+ Failure(err)
63
96
  end
97
+
98
+ alias :>= :try
64
99
 
65
100
  class Failure < Result
66
101
  class << self; public :new; end
@@ -1,3 +1,3 @@
1
1
  module Deterministic
2
- VERSION = "0.12.1"
2
+ VERSION = "0.13.1"
3
3
  end
data/lib/deterministic.rb CHANGED
@@ -6,7 +6,7 @@ module Deterministic; end
6
6
 
7
7
  require 'deterministic/monad'
8
8
  require 'deterministic/match'
9
- require 'deterministic/result/chain'
10
9
  require 'deterministic/result'
11
10
  require 'deterministic/option'
11
+ require 'deterministic/either'
12
12
  require 'deterministic/null'
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ include Deterministic
4
+
5
+ describe Deterministic::Either do
6
+ it "+ does not change operands" do
7
+ l = Left(1)
8
+ r = Right(2)
9
+
10
+ either = l + r
11
+ expect(l).to eq Left(1)
12
+ expect(r).to eq Right(2)
13
+ expect(either).to eq Either.new([1], [2])
14
+ end
15
+
16
+ it "allows adding multiple Eithers" do
17
+ either = Left(1) + Left(2) + Right(:a) + Right(:b)
18
+ expect(either.left).to eq [1, 2]
19
+ expect(either.right).to eq [:a, :b]
20
+ end
21
+
22
+ it "works" do
23
+ actual = [1, 2, 3, 4].inject(Either.new) { |acc, value|
24
+ acc + (value % 2 == 0 ? Right(value) : Left(value))
25
+ }
26
+ expect(actual).to eq Either.new([1, 3], [2, 4])
27
+ end
28
+
29
+ end
@@ -11,6 +11,7 @@ describe Deterministic::Option do
11
11
 
12
12
  # any?
13
13
  specify { expect(described_class.any?(nil)).to be_none }
14
+ specify { expect(described_class.any?(None)).to be_none }
14
15
  specify { expect(described_class.any?("")).to be_none }
15
16
  specify { expect(described_class.any?([])).to be_none }
16
17
  specify { expect(described_class.any?({})).to be_none }
@@ -21,21 +22,53 @@ describe Deterministic::Option do
21
22
  specify { expect(described_class.try! { raise "error" }).to be_none }
22
23
  end
23
24
 
24
- describe Deterministic::Option::Some do
25
- it_behaves_like 'a Monad' do
26
- let(:monad) { described_class }
27
- end
25
+ describe Deterministic::Option do
26
+ # it_behaves_like 'a Monad' do
27
+ # let(:monad) { described_class }
28
+ # end
29
+
30
+ specify { expect(Option::Some.new(0)).to be_a Option::Some }
31
+ specify { expect(Option::Some.new(0)).to eq Some(0) }
32
+
33
+ specify { expect(Option::None.new).to eq Option::None.new }
34
+ specify { expect(Option::None.new).to eq None }
35
+
36
+ # some?, none?
37
+ specify { expect(None.some?).to be_falsey }
38
+ specify { expect(None.none?).to be_truthy }
39
+ specify { expect(Some(0).some?).to be_truthy }
40
+ specify { expect(Some(0).none?).to be_falsey }
41
+
42
+ # value, value_or
43
+ specify { expect(Some(0).value).to eq 0 }
44
+ specify { expect(Some(1).value_or(2)).to eq 1}
45
+ specify { expect { None.value }.to raise_error NoMethodError }
46
+ specify { expect(None.value_or(2)).to eq 2}
47
+
48
+ # fmap
49
+ specify { expect(Some(1).fmap { |n| n + 1}).to eq Some(2) }
50
+ specify { expect(None.fmap { |n| n + 1}).to eq None }
51
+
52
+ # map
53
+ specify { expect(Some(1).map { |n| Some(n + 1)}).to eq Some(2) }
54
+ specify { expect(Some(1).map { |n| None }).to eq None }
55
+ specify { expect(None.map { |n| nil }).to eq None }
28
56
 
29
- specify { expect(described_class.new(0)).to be_a Option::Some }
30
- specify { expect(described_class.new(0)).to eq Some(0) }
31
- specify { expect(described_class.new(0).some?).to be_truthy }
32
- specify { expect(described_class.new(0).none?).to be_falsey }
33
- specify { expect(described_class.new(0).value).to eq 0 }
57
+ # to_a
58
+ specify { expect(Some(1).value_to_a). to eq Some([1])}
59
+ specify { expect(Some([1]).value_to_a). to eq Some([1])}
60
+ specify { expect(None.value_to_a). to eq None}
34
61
 
35
- specify { expect(described_class.new(1).fmap { |n| n + 1}).to eq Some(2) }
36
- specify { expect(described_class.new(1).map { |n| Some(n + 1)}).to eq Some(2) }
37
- specify { expect(described_class.new(1).map { |n| None }).to eq None }
62
+ # +
63
+ specify { expect(Some(1) + None).to eq Some(1) }
64
+ specify { expect(Some(1) + None + None).to eq Some(1) }
65
+ specify { expect(Some(1) + Some(1)).to eq Some(2) }
66
+ specify { expect(None + Some(1)).to eq Some(1) }
67
+ specify { expect(None + None + Some(1)).to eq Some(1) }
68
+ specify { expect(None + None + Some(1) + None).to eq Some(1) }
69
+ specify { expect { Some([1]) + Some(1)}.to raise_error TypeError}
38
70
 
71
+ # match
39
72
  specify {
40
73
  expect(
41
74
  Some(0).match {
@@ -75,18 +108,14 @@ describe Deterministic::Option::Some do
75
108
 
76
109
  end
77
110
 
78
- describe Deterministic::Option::None do
79
- # it_behaves_like 'a Monad' do
80
- # let(:monad) { described_class }
81
- # end
82
-
83
- specify { expect(described_class.new).to eq None }
84
- specify { expect(described_class.new.some?).to be_falsey }
85
- specify { expect(described_class.new.none?).to be_truthy }
86
- # specify { expect { described_class.new.value }.to raise_error RuntimeError }
111
+ describe Deterministic::Option::Some do
112
+ it_behaves_like 'a Monad' do
113
+ let(:monad) { described_class }
114
+ end
115
+ end
87
116
 
88
- specify { expect(described_class.new.fmap { |n| n + 1}).to eq None }
89
- specify { expect(described_class.new.map { |n| nil }).to eq None }
90
- specify { expect(described_class.new).to eq Option::None.new }
91
- specify { expect(described_class.new).to eq None }
117
+ describe Deterministic::Option::None do
118
+ it_behaves_like 'a Monad' do
119
+ let(:monad) { described_class }
120
+ end
92
121
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deterministic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Zolnierek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-26 00:00:00.000000000 Z
11
+ date: 2014-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,27 +127,28 @@ files:
127
127
  - lib/deterministic.rb
128
128
  - lib/deterministic/core_ext/object/result.rb
129
129
  - lib/deterministic/core_ext/result.rb
130
+ - lib/deterministic/either.rb
130
131
  - lib/deterministic/match.rb
131
132
  - lib/deterministic/maybe.rb
132
133
  - lib/deterministic/monad.rb
133
134
  - lib/deterministic/null.rb
134
135
  - lib/deterministic/option.rb
135
136
  - lib/deterministic/result.rb
136
- - lib/deterministic/result/chain.rb
137
137
  - lib/deterministic/version.rb
138
138
  - spec/examples/bookings_spec.rb
139
139
  - spec/examples/config_spec.rb
140
140
  - spec/examples/validate_address_spec.rb
141
141
  - spec/lib/deterministic/core_ext/object/either_spec.rb
142
142
  - spec/lib/deterministic/core_ext/result_spec.rb
143
+ - spec/lib/deterministic/either_spec.rb
143
144
  - spec/lib/deterministic/maybe_spec.rb
144
145
  - spec/lib/deterministic/monad_axioms.rb
145
146
  - spec/lib/deterministic/monad_spec.rb
146
147
  - spec/lib/deterministic/null_spec.rb
147
148
  - spec/lib/deterministic/option_spec.rb
148
- - spec/lib/deterministic/result/chain_spec.rb
149
149
  - spec/lib/deterministic/result/failure_spec.rb
150
150
  - spec/lib/deterministic/result/match_spec.rb
151
+ - spec/lib/deterministic/result/result_map.rb
151
152
  - spec/lib/deterministic/result/result_shared.rb
152
153
  - spec/lib/deterministic/result/success_spec.rb
153
154
  - spec/lib/deterministic/result_spec.rb
@@ -182,14 +183,15 @@ test_files:
182
183
  - spec/examples/validate_address_spec.rb
183
184
  - spec/lib/deterministic/core_ext/object/either_spec.rb
184
185
  - spec/lib/deterministic/core_ext/result_spec.rb
186
+ - spec/lib/deterministic/either_spec.rb
185
187
  - spec/lib/deterministic/maybe_spec.rb
186
188
  - spec/lib/deterministic/monad_axioms.rb
187
189
  - spec/lib/deterministic/monad_spec.rb
188
190
  - spec/lib/deterministic/null_spec.rb
189
191
  - spec/lib/deterministic/option_spec.rb
190
- - spec/lib/deterministic/result/chain_spec.rb
191
192
  - spec/lib/deterministic/result/failure_spec.rb
192
193
  - spec/lib/deterministic/result/match_spec.rb
194
+ - spec/lib/deterministic/result/result_map.rb
193
195
  - spec/lib/deterministic/result/result_shared.rb
194
196
  - spec/lib/deterministic/result/success_spec.rb
195
197
  - spec/lib/deterministic/result_spec.rb
@@ -1,27 +0,0 @@
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
-