divergent 0.1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7ba0cd2b5c2f7fe954da0d3d7606369605b4d258
4
+ data.tar.gz: f8647ef8978718d7e1f6723adf57972e571361ad
5
+ SHA512:
6
+ metadata.gz: d30e7e48cc2e25382f685b392c8bf06d018cdfffcaaa16289993bd61d72e24963824cd5eb1dbd3607aea77559a31d054bf2f57e9f6dbff8f4d91070796a25bfa
7
+ data.tar.gz: 480627d46e138a0715a4e7966b5e49f05059730a0911af63840f60ce296e725d708e240a30c08e823d9b0623473c4b862f1867eef855044a8b33d2b2cc5747a4
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Cao Jiafeng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Divergent
2
+
3
+ A collection of monads for handling error in ruby.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'divergent'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install divergent
20
+
21
+ ## Usage
22
+
23
+ Using `Try`:
24
+
25
+ ``` ruby
26
+ require 'divergent'
27
+
28
+ include Divergent
29
+
30
+ require 'uri'
31
+ def parse_url(url)
32
+ Try {
33
+ URI.parse url
34
+ }
35
+ end
36
+
37
+ success_url = parse_url("http://www.google.com") # => Success<http://www.google.com>
38
+
39
+ failed_url = parse_url(':google.com') #=> Failure<bad URI(is not URI?): :google.com>
40
+
41
+ ### get_or_else
42
+
43
+ failed_url.get_or_else URI('http://duckduckgo.com') #=> #<URI::HTTP http://duckduckgo.com>
44
+
45
+ ### chainable operations
46
+
47
+ # map
48
+ success_url.map(&:scheme) #=> Success<http>
49
+
50
+ failed_url.map(&:scheme) #=> Failure<bad URI(is not URI?): :google.com>
51
+
52
+ # fmap
53
+ parse_url("http://thisisnotagoodsite.com").fmap do |url|
54
+ Try { Net::HTTP.get(url) }
55
+ end
56
+
57
+ # each
58
+ parse_url("http://google.com").each { |url| p url.to_s }
59
+ # =>
60
+ # "http://google.com"
61
+
62
+ # filter
63
+ parse_url("http://google.com").filter { |url| url.scheme == "http" } #=> Success<http://google.com>
64
+ parse_url("http://google.com").filter { |url| url.scheme == "https" } #=> Failure<Predicate does not hold for http://google.com>
65
+
66
+ # recover from error
67
+ failed_url.recover do |error|
68
+ case error
69
+ when NoMethodError
70
+ :no_method
71
+ when StandardError
72
+ :standard_error
73
+ else
74
+ :others
75
+ end
76
+ end #=> Success<standard_error>
77
+ ```
78
+
79
+
80
+ `Maybe` has similar interface to `Try`.
81
+ `Maybe` uses `None` instead of `Failure`.
82
+
83
+ ``` ruby
84
+ # provide default value
85
+ user = Maybe.unit User.find('a_non_exist_id')
86
+ user.get_or_else(default_user)
87
+ user.or_else(Maybe.unit User.find_by_name("username"))
88
+
89
+ # usage as a collection
90
+ user.each { |u| p u}
91
+ user.map(&:age)
92
+ user.fmap { |u| Maybe(u.gender) }
93
+ user.filter { |u| u.age > 20 }
94
+ ```
95
+
96
+ ## Contributing
97
+
98
+ Bug reports and pull requests are welcome on GitHub at https://github.com/lerencao/divergent.rb.
99
+
100
+
101
+ ## License
102
+
103
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
104
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "divergent"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/divergent.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'divergent/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "divergent"
8
+ spec.version = Divergent::VERSION
9
+ spec.authors = ["Cao Jiafeng"]
10
+ spec.email = ["funfriendcjf@gmail.com"]
11
+
12
+ spec.summary = %q{a collection of monad implemented in ruby inspired by scala}
13
+ spec.description = %q{the collection provides class handling errors in ruby}
14
+ spec.homepage = "http://github.com/lerencao/devergent.rb"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "pry"
21
+ spec.add_development_dependency "bundler", "~> 1.11"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest", "~> 5.0"
24
+ end
data/lib/divergent.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'divergent/version'
2
+ require 'divergent/try'
3
+ require 'divergent/maybe'
4
+
5
+
6
+ ##
7
+ # Divergent is a collection of monad class to do error handling in Ruby.
8
+ #
9
+ # Currently, it only contains two class:
10
+ # 1. Try: a container which can wraps possible errors.
11
+ # 2. Maybe: a container which wraps nil case.
12
+ module Divergent
13
+ end
@@ -0,0 +1,7 @@
1
+ module Divergent
2
+ class UnSupportedOperationError < StandardError
3
+ end
4
+
5
+ class NoSuchElementError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,248 @@
1
+ require 'singleton'
2
+
3
+ require_relative 'errors'
4
+ require_relative 'monad'
5
+
6
+ module Divergent
7
+ ##
8
+ # Represents optional values. Instances of Maybe
9
+ # are either an instance of Some or the object None.
10
+ #
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`.
14
+ class Maybe
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
+ ##
31
+ # An factory which creates Some(v) if the argument is not nil,
32
+ # and None if it is nil.
33
+ #
34
+ # Examples:
35
+ #
36
+ # ```
37
+ # Maybe.unit(1) # => Some(1)
38
+ # Maybe.unit(nil) # => None
39
+ # ```
40
+ def self.unit(v)
41
+ if v.nil?
42
+ None
43
+ else
44
+ Some.new(v)
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Returns the result of applying block to this Maybe value,
50
+ # if this value is not empty.
51
+ # Return `None` if this value is empty.
52
+ #
53
+ # Slightly different from `map` in that block is expected to
54
+ # return an instance of `Maybe`.
55
+ #
56
+ # Examples
57
+ #
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
+ # ```
63
+ def fmap() # :yields: v
64
+ if empty?
65
+ None
66
+ else
67
+ yield(get)
68
+ end
69
+ end
70
+
71
+ ##
72
+ # Return true if the maybe is None, false otherwise.
73
+ def empty?
74
+ raise NotImplementedError
75
+ end
76
+
77
+ ##
78
+ # Return the maybe's value.
79
+ #
80
+ # Notes:
81
+ # the maybe should not be empty.
82
+ #
83
+ # otherwise, raise Standarderror.
84
+ def get
85
+ raise NotImplementedError
86
+ end
87
+
88
+ ##
89
+ # Returns the maybe's value if the maybe is nonempty, otherwise
90
+ # return the `v`.
91
+ def get_or_else(v)
92
+ if empty?
93
+ v
94
+ else
95
+ get
96
+ end
97
+ end
98
+
99
+ ##
100
+ # Return this maybe id it is not empty,
101
+ # else return the `v`.
102
+ #
103
+ # Note:
104
+ # This is similar to Maybe#get_or_else,
105
+ # but the v should be an instance of Maybe.
106
+ def or_else(v)
107
+ if empty?
108
+ v
109
+ else
110
+ self
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Return a Maybe containing the result of applying block to the maybe's value
116
+ # if not empty.
117
+ # Otherwise, return None.
118
+
119
+ # Notes:
120
+ # This is similar to +flat_map+ except here,
121
+ # block does not need to wrap its result in a maybe.
122
+ def map() # :yields: v
123
+ if empty?
124
+ None
125
+ else
126
+ Maybe.unit(yield get)
127
+ end
128
+ end
129
+
130
+
131
+ ##
132
+ # Return this maybe if it is not empty and the predicate block evals to true.
133
+ # Otherwise, return None.
134
+ def filter() # :yields: v
135
+ if !empty? && yield(get)
136
+ self
137
+ else
138
+ None
139
+ end
140
+ end
141
+
142
+ ##
143
+ # Test whether the maybe contains a given elem.
144
+ #
145
+ # Examples:
146
+ #
147
+ # ```
148
+ # Maybe.unit(1).include?(1) #=> true
149
+ # Maybe.unit(1).include?(2) #=> false
150
+ # Maybe.empty.include?(1) #=> false
151
+ # ```
152
+ def include?(elem)
153
+ !empty? && get == elem
154
+ end
155
+
156
+ ##
157
+ # Return true if it is not empty and the predicate block evals to true.
158
+ #
159
+ # Examples:
160
+ #
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
+ # ```
166
+ def any?() # :yields: v
167
+ !empty? && yield(get)
168
+ end
169
+
170
+ ##
171
+ # Return true if it is empty or the predicate block evals to true
172
+ # when applying to the maybe's value.
173
+ #
174
+ # Examples:
175
+ #
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
+ # ```
181
+ def all?() # :yields: v
182
+ empty? || yield(get)
183
+ end
184
+ ##
185
+ # Apply the given block to the maybe's value if not empty.
186
+ # Otherwise, do nothing.
187
+ def each() # :yields: v
188
+ yield(get) unless empty?
189
+ end
190
+
191
+ ## Returns a singleton list containing the maybe's value
192
+ # if it is nonempty, or the empty list if empty.
193
+ def to_a
194
+ if empty?
195
+ []
196
+ else
197
+ [get]
198
+ end
199
+ end
200
+ end
201
+
202
+ class Some < Maybe # :nodoc: all
203
+ def initialize(v)
204
+ raise 'value cannot be nil' if v.nil?
205
+ @v = v
206
+ end
207
+
208
+ def empty?
209
+ false
210
+ end
211
+
212
+ def get
213
+ @v
214
+ end
215
+
216
+ def to_s
217
+ "Some(#{@v.inspect})"
218
+ end
219
+
220
+ alias inspect to_s
221
+ end
222
+
223
+ None = Class.new(Maybe) do # :nodoc: all
224
+ include Singleton
225
+
226
+ def empty?
227
+ true
228
+ end
229
+
230
+ def get
231
+ raise NoSuchElementError, 'no such element in None.get'
232
+ end
233
+
234
+ def to_s
235
+ "None"
236
+ end
237
+
238
+ alias inspect to_s
239
+ end.instance.freeze
240
+ end
241
+
242
+ module Divergent
243
+ def Maybe(v)
244
+ Maybe.unit(v)
245
+ end
246
+
247
+ module_function :Maybe
248
+ end
@@ -0,0 +1,20 @@
1
+ module Divergent
2
+ ##
3
+ # The module defines the interfaces that other class should implement.
4
+ #
5
+ # Examples:
6
+ #
7
+ # ```
8
+ # Maybe.unit(1) # => Some(1)
9
+ # Maybe.unit(1).fmap { |v| v + 1 } => Some(2)
10
+ # ```
11
+ module Monad
12
+ def self.unit(v)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def fmap(&f)
17
+ raise NotImplementedError
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,296 @@
1
+ require_relative 'errors'
2
+ require_relative 'monad'
3
+
4
+ module Divergent
5
+ ##
6
+ # The `Try` type represents a computation that
7
+ # may either result in an exception, or return a
8
+ # successfully computed value.
9
+ # It's similar to, but semantically different from Either.
10
+ #
11
+ # Instances of Try, are either an instance of Success or Failure.
12
+ #
13
+ # For example, `Try` can be used to perform division on a user-defined input,
14
+ # without the need to do explicit exception-handling in
15
+ # all of the places that an exception might occur.
16
+ module Try
17
+ include Monad
18
+ def self.unit(v)
19
+ Success.new(v)
20
+ end
21
+
22
+ # Returns `true` if the `Try` is a `Failure`, `false` otherwise.
23
+ def failure?
24
+ raise NotImplementedError
25
+ end
26
+
27
+ # Returns `true` if the `Try` is a `Success`, `false` otherwise.
28
+ def success?
29
+ raise NotImplementedError
30
+ end
31
+
32
+ # Returns the value from this `Success`
33
+ # or the given `default` argument if this is a `Failure`.
34
+ def get_or_else(default)
35
+ if success?
36
+ get
37
+ else
38
+ default
39
+ end
40
+ end
41
+
42
+ # Returns this `Try` if it's a `Success`
43
+ # or the given `default` argument if this is a `Failure`.
44
+ #
45
+ # Notes: the `default` value should be an instance of Try.
46
+ def or_else(default)
47
+ if success?
48
+ self
49
+ else
50
+ default
51
+ end
52
+ end
53
+
54
+ # Returns the value from this `Success`
55
+ # or throws the exception if this is a `Failure`.
56
+ def get
57
+ raise NotImplementedError
58
+ end
59
+
60
+ ##
61
+ # Applies the given block if this is a `Success`,
62
+ # otherwise returns `Unit` if this is a `Failure`.
63
+ #
64
+ # Notes:
65
+ #
66
+ # If block throws, then this method may throw an exception.
67
+ def each(&block)
68
+ raise NotImplementedError
69
+ end
70
+
71
+ ##
72
+ # Maps the given function to the value from this `Success`
73
+ # or returns this if this is a `Failure`.
74
+ def map(&block)
75
+ raise NotImplementedError
76
+ end
77
+
78
+ # Converts this to a `Failure` if the predicate is not satisfied.
79
+ def filter(&block)
80
+ raise NotImplementedError
81
+ end
82
+
83
+ # Applies the given block if this is a `Failure`,
84
+ # otherwise returns this if this is a `Success`.
85
+ #
86
+ # Notes: block call should return an instance of Try.
87
+ # This is like `fmap` for the exception.
88
+ def recover_with(&block)
89
+ raise NotImplementedError
90
+ end
91
+
92
+ # Applies the given block if this is a `Failure`,
93
+ # otherwise returns this if this is a `Success`.
94
+ #
95
+ # This is like `fmap` for the exception.
96
+ def recover(&block)
97
+ raise NotImplementedError
98
+ end
99
+
100
+ # Transforms a nested `Try` into an un-nested `Try`.
101
+ def flatten
102
+ raise NotImplementedError
103
+ end
104
+
105
+ ##
106
+ # Inverts this `Try`. If this is a `Failure`, returns its exception wrapped in a `Success`.
107
+ # If this is a `Success`, returns a `Failure` containing an UnSupportedOperationError.
108
+ def failed
109
+ raise NotImplementedError
110
+ end
111
+
112
+ ##
113
+ # Completes this `Try` by applying the function `f` to this if this is of type `Failure`,
114
+ # or conversely, by applying `s` if this is a `Success`.
115
+ def transform(s, f)
116
+ raise NotImplementedError
117
+ end
118
+ end
119
+
120
+ class Success # :nodoc: true
121
+ include Try
122
+
123
+ def initialize(value)
124
+ @value = value
125
+ end
126
+
127
+ def fmap()
128
+ begin
129
+ yield @value
130
+ rescue => e
131
+ Failure.new(e)
132
+ end
133
+ end
134
+
135
+ def success?
136
+ true
137
+ end
138
+
139
+ def failure?
140
+ false
141
+ end
142
+
143
+ def get
144
+ @value
145
+ end
146
+
147
+ def each()
148
+ yield(@value)
149
+ nil
150
+ end
151
+
152
+ def map()
153
+ t = begin
154
+ yield(@value)
155
+ rescue => e
156
+ Failure.new(e)
157
+ end
158
+
159
+ Success.new(t)
160
+ end
161
+
162
+ def filter()
163
+ p = begin
164
+ yield(@value)
165
+ rescue => e
166
+ return Failure.new(e)
167
+ end
168
+ if p
169
+ self
170
+ else
171
+ Failure.new(NoSuchElementError.new("Predicate does not hold for #{@value}"))
172
+ end
173
+ end
174
+
175
+ def recover_with(&block)
176
+ self
177
+ end
178
+
179
+ def recover(&block)
180
+ self
181
+ end
182
+
183
+ def failed
184
+ Failure.new(UnSupportedOperationError.new('Success.failed'))
185
+ end
186
+
187
+ def transform(s, _f)
188
+ begin
189
+ s.call(@value)
190
+ rescue => e
191
+ Failure.new(e)
192
+ end
193
+ end
194
+
195
+ def flatten
196
+ if @value.is_a? Try
197
+ @value
198
+ else
199
+ self
200
+ end
201
+ end
202
+
203
+ def to_s
204
+ "Success<#{@value}>"
205
+ end
206
+
207
+ alias inspect to_s
208
+ end
209
+
210
+ class Failure # :nodoc: true
211
+ include Try
212
+ def initialize(error)
213
+ raise 'error should be an StandardError' unless error.is_a? StandardError
214
+ @error = error
215
+ end
216
+
217
+ def fmap()
218
+ self
219
+ end
220
+
221
+ def failure?
222
+ true
223
+ end
224
+
225
+ def success?
226
+ false
227
+ end
228
+
229
+ def get
230
+ raise @error
231
+ end
232
+
233
+ def each(&block)
234
+ nil
235
+ end
236
+
237
+ def map(&block)
238
+ self
239
+ end
240
+
241
+ def filter(&block)
242
+ self
243
+ end
244
+
245
+ def recover_with()
246
+ begin
247
+ yield(@error)
248
+ rescue => e
249
+ Failure.new(e)
250
+ end
251
+ end
252
+
253
+ def recover()
254
+ t = yield(@error)
255
+ Success.new(t)
256
+ rescue => e
257
+ return Failure.new(e)
258
+ end
259
+
260
+ def failed
261
+ Success.new(@error)
262
+ end
263
+
264
+ def transform(_s, f)
265
+ begin
266
+ f.call(@error)
267
+ rescue => e
268
+ Failure.new(e)
269
+ end
270
+ end
271
+
272
+ def flatten
273
+ self
274
+ end
275
+
276
+ def to_s
277
+ "Failure<#{@error}>"
278
+ end
279
+
280
+ alias inspect to_s
281
+ end
282
+ end
283
+
284
+
285
+ module Divergent
286
+ ##
287
+ # Constructs a `Try` by calling the passed block. This
288
+ # method will ensure any StandardError is caught and a
289
+ # `Failure` object is returned.
290
+ def Try
291
+ Success.new(yield)
292
+ rescue => e
293
+ Failure.new(e)
294
+ end
295
+ module_function :Try
296
+ end
@@ -0,0 +1,3 @@
1
+ module Divergent
2
+ VERSION = "0.1.2"
3
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: divergent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Cao Jiafeng
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: the collection provides class handling errors in ruby
70
+ email:
71
+ - funfriendcjf@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/console
83
+ - bin/setup
84
+ - divergent.gemspec
85
+ - lib/divergent.rb
86
+ - lib/divergent/errors.rb
87
+ - lib/divergent/maybe.rb
88
+ - lib/divergent/monad.rb
89
+ - lib/divergent/try.rb
90
+ - lib/divergent/version.rb
91
+ homepage: http://github.com/lerencao/devergent.rb
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.4.5.1
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: a collection of monad implemented in ruby inspired by scala
115
+ test_files: []