deterministic 0.12.1 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-