divergent 0.1.4 → 0.2.0

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: a97dcb4c7b94772af15a5cc9ec0d794c163a29cf
4
- data.tar.gz: fe5ed5e4799c1f2a78421f68e88ac579ec9fb23d
3
+ metadata.gz: 6f041ffcec9e7a3a5287941abf2e229cd6644229
4
+ data.tar.gz: 6ce3a0fe3cd1798cd1a96cf7f27a9e79f36fa871
5
5
  SHA512:
6
- metadata.gz: 8494b52fd3c7c7b5d8dc22577ebd6d25059213c3860ea798cf2527cc3c9f8e7b86dfe29c93247ddef227c130976d2ac30cca3e5bf90bc62730d008faac6c00e7
7
- data.tar.gz: 5ba285bb235e644015c16f1dc8153f1fa3f4ee8ce6f526006b3d93fb593315ed03d2edc39667ccbbb02eb0c115cb61373ef94dc931098429dc87b33e1d413636
6
+ metadata.gz: 2c19e6ec8931dc0d5a719c5ac5a6fd8603badd8672cab190106effac007230f9a281824b6dfd5c18ecd05d264ced8cf5be879565d2064d3131b8626820f0dd16
7
+ data.tar.gz: 0170760e83aed59e80d28b741b4adc7e947a222773292481956bd332907e7b8aeca0c16d11f741c64450fba7f46c4f3d8b7a9eaa574605e623207bff7572e22d
data/README.md CHANGED
@@ -79,9 +79,9 @@ Try { 1 / 0 }.recover(ZeroDivisionError, &:message)
79
79
 
80
80
  ``` ruby
81
81
  # provide default value
82
- user = Maybe.unit User.find('a_non_exist_id')
82
+ user = Maybe(User.find('a_non_exist_id'))
83
83
  user.get_or_else(default_user)
84
- user.or_else(Maybe.unit User.find_by_name("username"))
84
+ user.or_else Maybe(User.find_by_name("username"))
85
85
 
86
86
  # usage as a collection
87
87
  user.each { |u| p u}
@@ -5,38 +5,23 @@ require_relative 'monad'
5
5
 
6
6
  module Divergent
7
7
  ##
8
- # Represents optional values. Instances of Maybe
9
- # are either an instance of Some or the object None.
8
+ # == Optional values.
10
9
  #
11
- # The most idiomatic way to use an Maybe instance is to treat it
12
- # as a collection or monad and use `map`, `fmap`, `filter`, or
13
- # `each`.
10
+ # An instance of Some or the object None.
11
+ #
12
+ # The most idiomatic way to use an Maybe instance is to treat it
13
+ # as a collection or monad and use `map`, `fmap`, `filter`, or `each`.
14
14
  class Maybe
15
15
  include Monad
16
-
17
- ##
18
- # An Maybe factory which return None.
19
- # This always return the same None object.
20
- #
21
- # Example:
22
- #
23
- # ```
24
- # Maybe.empty == Maybe.empty
25
- # ```
26
- def self.empty
27
- None
28
- end
29
-
30
16
  ##
31
17
  # An factory which creates Some(v) if the argument is not nil,
32
18
  # and None if it is nil.
33
19
  #
34
20
  # Examples:
35
21
  #
36
- # ```
37
- # Maybe.unit(1) # => Some(1)
38
- # Maybe.unit(nil) # => None
39
- # ```
22
+ # Maybe.unit(1) # => Some(1)
23
+ # Maybe.unit(nil) # => None
24
+ #
40
25
  def self.unit(v)
41
26
  if v.nil?
42
27
  None
@@ -45,6 +30,20 @@ module Divergent
45
30
  end
46
31
  end
47
32
 
33
+
34
+ ##
35
+ # An Maybe factory which return None.
36
+ #
37
+ # This always return the same None object.
38
+ #
39
+ # Example:
40
+ #
41
+ # Maybe.empty == Maybe.empty
42
+ #
43
+ def self.empty
44
+ None
45
+ end
46
+
48
47
  ##
49
48
  # Returns the result of applying block to this Maybe value,
50
49
  # if this value is not empty.
@@ -55,11 +54,10 @@ module Divergent
55
54
  #
56
55
  # Examples
57
56
  #
58
- # ```
59
- # Maybe.unit(1).fmap { |v| Maybe.unit(v + 1) } # => Some(2)
60
- # some_hash = {}
61
- # Maybe.unit(:a).fmap { |v| Maybe.unit(some_hash[v]) } # => None
62
- # ```
57
+ # Maybe.unit(1).fmap { |v| Maybe.unit(v + 1) } # => Some(2)
58
+ # some_hash = {}
59
+ # Maybe.unit(:a).fmap { |v| Maybe.unit(some_hash[v]) } # => None
60
+ #
63
61
  def fmap() # :yields: v
64
62
  if empty?
65
63
  None
@@ -120,11 +118,7 @@ module Divergent
120
118
  # This is similar to +flat_map+ except here,
121
119
  # block does not need to wrap its result in a maybe.
122
120
  def map() # :yields: v
123
- if empty?
124
- None
125
- else
126
- Maybe.unit(yield get)
127
- end
121
+ fmap { |v| Maybe.unit(yield v) }
128
122
  end
129
123
 
130
124
 
@@ -132,10 +126,8 @@ module Divergent
132
126
  # Return this maybe if it is not empty and the predicate block evals to true.
133
127
  # Otherwise, return None.
134
128
  def filter() # :yields: v
135
- if !empty? && yield(get)
136
- self
137
- else
138
- None
129
+ fmap do |v|
130
+ yield(v) ? Maybe.unit(v) : None
139
131
  end
140
132
  end
141
133
 
@@ -144,11 +136,11 @@ module Divergent
144
136
  #
145
137
  # Examples:
146
138
  #
147
- # ```
148
- # Maybe.unit(1).include?(1) #=> true
149
- # Maybe.unit(1).include?(2) #=> false
150
- # Maybe.empty.include?(1) #=> false
151
- # ```
139
+ #
140
+ # Maybe.unit(1).include?(1) #=> true
141
+ # Maybe.unit(1).include?(2) #=> false
142
+ # Maybe.empty.include?(1) #=> false
143
+ #
152
144
  def include?(elem)
153
145
  !empty? && get == elem
154
146
  end
@@ -158,11 +150,11 @@ module Divergent
158
150
  #
159
151
  # Examples:
160
152
  #
161
- # ```
162
- # Maybe.unit(1).any?{ |v| v == 1} #=> true
163
- # Maybe.unit(1).any?{ |v| v == 2} #=> false
164
- # Maybe.empty.any?{ |v| v == 1} #=> false
165
- # ```
153
+ #
154
+ # Maybe.unit(1).any?{ |v| v == 1} #=> true
155
+ # Maybe.unit(1).any?{ |v| v == 2} #=> false
156
+ # Maybe.empty.any?{ |v| v == 1} #=> false
157
+ #
166
158
  def any?() # :yields: v
167
159
  !empty? && yield(get)
168
160
  end
@@ -173,11 +165,11 @@ module Divergent
173
165
  #
174
166
  # Examples:
175
167
  #
176
- # ```
177
- # Maybe.unit(1).all?{ |v| v == 1} #=> true
178
- # Maybe.unit(1).all?{ |v| v == 2} #=> false
179
- # Maybe.empty.all?{ |v| v == 1} #=> true
180
- # ```
168
+ #
169
+ # Maybe.unit(1).all?{ |v| v == 1} #=> true
170
+ # Maybe.unit(1).all?{ |v| v == 2} #=> false
171
+ # Maybe.empty.all?{ |v| v == 1} #=> true
172
+ #
181
173
  def all?() # :yields: v
182
174
  empty? || yield(get)
183
175
  end
@@ -4,17 +4,26 @@ module Divergent
4
4
  #
5
5
  # Examples:
6
6
  #
7
- # ```
8
- # Maybe.unit(1) # => Some(1)
9
- # Maybe.unit(1).fmap { |v| v + 1 } => Some(2)
10
- # ```
7
+ #
8
+ # Maybe.unit(1) # => Some(1)
9
+ # Maybe.unit(1).fmap { |v| v + 1 } => Some(2)
10
+ #
11
11
  module Monad
12
- def self.unit(v)
13
- raise NotImplementedError
12
+ module InstanceMethods
13
+ def fmap(&f)
14
+ raise NotImplementedError
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def unit(v)
20
+ raise NotImplementedError
21
+ end
14
22
  end
15
23
 
16
- def fmap(&f)
17
- raise NotImplementedError
24
+ def self.included(subclass)
25
+ subclass.extend ClassMethods
26
+ subclass.include InstanceMethods
18
27
  end
19
28
  end
20
29
  end
@@ -15,8 +15,10 @@ module Divergent
15
15
  # all of the places that an exception might occur.
16
16
  module Try
17
17
  include Monad
18
- def self.unit(v)
19
- Success.new(v)
18
+ def self.unit()
19
+ Success.new(yield)
20
+ rescue => e
21
+ Failure.new(e)
20
22
  end
21
23
 
22
24
  # Returns `true` if the `Try` is a `Failure`, `false` otherwise.
@@ -84,6 +86,7 @@ module Divergent
84
86
  # otherwise returns this if this is a `Success`.
85
87
  #
86
88
  # Notes: block call should return an instance of Try.
89
+ # And, error raised from the block call will not rescued by it!
87
90
  # This is like `fmap` for the exception.
88
91
  def recover_with(&block)
89
92
  raise NotImplementedError
@@ -93,6 +96,7 @@ module Divergent
93
96
  # and leave other error case unrecoverd.
94
97
  # If no class is given, recover it anyway.
95
98
  # The error instance(if this is a Failure) will be passed into the block.
99
+ # And, error raised from the block call will not rescued by it!
96
100
  # Otherwise returns this if this is a `Success`.
97
101
  #
98
102
  # This is like `fmap` for the exception.
@@ -156,25 +160,18 @@ module Divergent
156
160
  end
157
161
 
158
162
  def map()
159
- t = begin
160
- yield(@value)
161
- rescue => e
162
- Failure.new(e)
163
- end
164
-
165
- Success.new(t)
163
+ fmap do |v|
164
+ Try.unit { yield v }
165
+ end
166
166
  end
167
167
 
168
168
  def filter()
169
- p = begin
170
- yield(@value)
171
- rescue => e
172
- return Failure.new(e)
173
- end
174
- if p
175
- self
176
- else
177
- Failure.new(NoSuchElementError.new("Predicate does not hold for #{@value}"))
169
+ fmap do |v|
170
+ if yield(v)
171
+ self
172
+ else
173
+ Failure.new(NoSuchElementError.new("Predicate does not hold for #{v}"))
174
+ end
178
175
  end
179
176
  end
180
177
 
@@ -249,11 +246,7 @@ module Divergent
249
246
  end
250
247
 
251
248
  def recover_with()
252
- begin
253
- yield(@error)
254
- rescue => e
255
- Failure.new(e)
256
- end
249
+ yield(@error)
257
250
  end
258
251
 
259
252
  def recover(*errors)
@@ -264,12 +257,8 @@ module Divergent
264
257
 
265
258
  raise 'no block given' unless block_given?
266
259
 
267
- begin
268
- t = yield(@error)
269
- Success.new(t)
270
- rescue => e
271
- Failure.new(e)
272
- end
260
+ t = yield(@error)
261
+ Success.new(t)
273
262
  end
274
263
 
275
264
  def failed
@@ -303,9 +292,7 @@ module Divergent
303
292
  # method will ensure any StandardError is caught and a
304
293
  # `Failure` object is returned.
305
294
  def Try
306
- Success.new(yield)
307
- rescue => e
308
- Failure.new(e)
295
+ Try.unit { yield }
309
296
  end
310
297
  module_function :Try
311
298
  end
@@ -1,3 +1,3 @@
1
1
  module Divergent
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: divergent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cao Jiafeng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-26 00:00:00.000000000 Z
11
+ date: 2016-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  version: '0'
110
110
  requirements: []
111
111
  rubyforge_project:
112
- rubygems_version: 2.5.1
112
+ rubygems_version: 2.4.5.1
113
113
  signing_key:
114
114
  specification_version: 4
115
115
  summary: a collection of monad implemented in ruby inspired by scala