mprelude 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19538ca2618de1e9e66da6b29c8e173ba3d1ce1e967ccaa7f87c71685f7c1e13
4
+ data.tar.gz: 83f2a0ae363a6227f7da56dc6e399e330a15a4eb74ca4acb6c0c1ec971db07d2
5
+ SHA512:
6
+ metadata.gz: d166a903c908906e55f62e50d4fc7a3863bed413ddd15c55b923330009069b5080d9d459b14981ca5a70ead7a34e7567d81d33cc6f000b4d8e2c2b74770fe1a1
7
+ data.tar.gz: b11d18eac0aad4eb2a14b6d5c22c8e201b27b41769df771cd9b71ad155ad57ff4dbb14f35cc946b8724b520c9f34f0a2f4ecadd1e64dbb4b99dcff525c3171e9
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ --format progress
3
+ --order random
4
+ --require spec_helper
5
+ --warnings
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'mutant', '~> 0.8.24'
9
+ gem 'mutant-rspec', '~> 0.8.24'
10
+ end
11
+
12
+ gem(
13
+ 'devtools',
14
+ git: 'https://github.com/mbj/devtools.git',
15
+ ref: '26ba0a1053e6cf7b79fc72d513a73457f9a38ead'
16
+ )
data/Gemfile.lock ADDED
@@ -0,0 +1,184 @@
1
+ GIT
2
+ remote: https://github.com/mbj/devtools.git
3
+ revision: 26ba0a1053e6cf7b79fc72d513a73457f9a38ead
4
+ ref: 26ba0a1053e6cf7b79fc72d513a73457f9a38ead
5
+ specs:
6
+ devtools (0.1.23)
7
+ abstract_type (~> 0.0.7)
8
+ adamantium (~> 0.2.0)
9
+ anima (~> 0.3.0)
10
+ concord (~> 0.1.5)
11
+ flay (~> 2.12.0)
12
+ flog (~> 4.6.2)
13
+ procto (~> 0.0.3)
14
+ rake (~> 12.3.0)
15
+ reek (~> 5.3.0)
16
+ rspec (~> 3.8.0)
17
+ rspec-core (~> 3.8.0)
18
+ rspec-its (~> 1.2.0)
19
+ rubocop (~> 0.61.1)
20
+ simplecov (~> 0.16.1)
21
+ yard (~> 0.9.16)
22
+ yardstick (~> 0.9.9)
23
+
24
+ PATH
25
+ remote: .
26
+ specs:
27
+ mprelude (0.0.1)
28
+ abstract_type (~> 0.0.7)
29
+ adamantium (~> 0.2.0)
30
+ concord (~> 0.1.5)
31
+ equalizer (~> 0.0.9)
32
+ ice_nine (~> 0.11.1)
33
+ procto (~> 0.0.2)
34
+
35
+ GEM
36
+ remote: https://rubygems.org/
37
+ specs:
38
+ abstract_type (0.0.7)
39
+ adamantium (0.2.0)
40
+ ice_nine (~> 0.11.0)
41
+ memoizable (~> 0.4.0)
42
+ anima (0.3.1)
43
+ abstract_type (~> 0.0.7)
44
+ adamantium (~> 0.2)
45
+ equalizer (~> 0.0.11)
46
+ ast (2.4.0)
47
+ axiom-types (0.1.1)
48
+ descendants_tracker (~> 0.0.4)
49
+ ice_nine (~> 0.11.0)
50
+ thread_safe (~> 0.3, >= 0.3.1)
51
+ codeclimate-engine-rb (0.4.1)
52
+ virtus (~> 1.0)
53
+ coercible (1.0.0)
54
+ descendants_tracker (~> 0.0.1)
55
+ concord (0.1.5)
56
+ adamantium (~> 0.2.0)
57
+ equalizer (~> 0.0.9)
58
+ descendants_tracker (0.0.4)
59
+ thread_safe (~> 0.3, >= 0.3.1)
60
+ diff-lcs (1.3)
61
+ docile (1.3.2)
62
+ equalizer (0.0.11)
63
+ erubis (2.7.0)
64
+ flay (2.12.0)
65
+ erubis (~> 2.7.0)
66
+ path_expander (~> 1.0)
67
+ ruby_parser (~> 3.0)
68
+ sexp_processor (~> 4.0)
69
+ flog (4.6.2)
70
+ path_expander (~> 1.0)
71
+ ruby_parser (~> 3.1, > 3.1.0)
72
+ sexp_processor (~> 4.8)
73
+ ice_nine (0.11.2)
74
+ jaro_winkler (1.5.3)
75
+ json (2.2.0)
76
+ kwalify (0.7.2)
77
+ memoizable (0.4.2)
78
+ thread_safe (~> 0.3, >= 0.3.1)
79
+ morpher (0.2.6)
80
+ abstract_type (~> 0.0.7)
81
+ adamantium (~> 0.2.0)
82
+ anima (~> 0.3.0)
83
+ ast (~> 2.2)
84
+ concord (~> 0.1.5)
85
+ equalizer (~> 0.0.9)
86
+ ice_nine (~> 0.11.0)
87
+ procto (~> 0.0.2)
88
+ mutant (0.8.24)
89
+ abstract_type (~> 0.0.7)
90
+ adamantium (~> 0.2.0)
91
+ anima (~> 0.3.0)
92
+ ast (~> 2.2)
93
+ concord (~> 0.1.5)
94
+ diff-lcs (~> 1.3)
95
+ equalizer (~> 0.0.9)
96
+ ice_nine (~> 0.11.1)
97
+ memoizable (~> 0.4.2)
98
+ morpher (~> 0.2.6)
99
+ parser (~> 2.5.1)
100
+ procto (~> 0.0.2)
101
+ regexp_parser (~> 1.2)
102
+ unparser (~> 0.4.2)
103
+ mutant-rspec (0.8.24)
104
+ mutant (~> 0.8.24)
105
+ rspec-core (>= 3.4.0, < 4.0.0)
106
+ parallel (1.17.0)
107
+ parser (2.5.3.0)
108
+ ast (~> 2.4.0)
109
+ path_expander (1.0.4)
110
+ powerpack (0.1.2)
111
+ procto (0.0.3)
112
+ psych (3.1.0)
113
+ rainbow (3.0.0)
114
+ rake (12.3.3)
115
+ reek (5.3.2)
116
+ codeclimate-engine-rb (~> 0.4.0)
117
+ kwalify (~> 0.7.0)
118
+ parser (>= 2.5.0.0, < 2.7, != 2.5.1.1)
119
+ psych (~> 3.1.0)
120
+ rainbow (>= 2.0, < 4.0)
121
+ regexp_parser (1.6.0)
122
+ rspec (3.8.0)
123
+ rspec-core (~> 3.8.0)
124
+ rspec-expectations (~> 3.8.0)
125
+ rspec-mocks (~> 3.8.0)
126
+ rspec-core (3.8.2)
127
+ rspec-support (~> 3.8.0)
128
+ rspec-expectations (3.8.4)
129
+ diff-lcs (>= 1.2.0, < 2.0)
130
+ rspec-support (~> 3.8.0)
131
+ rspec-its (1.2.0)
132
+ rspec-core (>= 3.0.0)
133
+ rspec-expectations (>= 3.0.0)
134
+ rspec-mocks (3.8.1)
135
+ diff-lcs (>= 1.2.0, < 2.0)
136
+ rspec-support (~> 3.8.0)
137
+ rspec-support (3.8.2)
138
+ rubocop (0.61.1)
139
+ jaro_winkler (~> 1.5.1)
140
+ parallel (~> 1.10)
141
+ parser (>= 2.5, != 2.5.1.1)
142
+ powerpack (~> 0.1)
143
+ rainbow (>= 2.2.2, < 4.0)
144
+ ruby-progressbar (~> 1.7)
145
+ unicode-display_width (~> 1.4.0)
146
+ ruby-progressbar (1.10.1)
147
+ ruby_parser (3.13.1)
148
+ sexp_processor (~> 4.9)
149
+ sexp_processor (4.12.1)
150
+ simplecov (0.16.1)
151
+ docile (~> 1.1)
152
+ json (>= 1.8, < 3)
153
+ simplecov-html (~> 0.10.0)
154
+ simplecov-html (0.10.2)
155
+ thread_safe (0.3.6)
156
+ unicode-display_width (1.4.1)
157
+ unparser (0.4.2)
158
+ abstract_type (~> 0.0.7)
159
+ adamantium (~> 0.2.0)
160
+ concord (~> 0.1.5)
161
+ diff-lcs (~> 1.3)
162
+ equalizer (~> 0.0.9)
163
+ parser (>= 2.3.1.2, < 2.6)
164
+ procto (~> 0.0.2)
165
+ virtus (1.0.5)
166
+ axiom-types (~> 0.1)
167
+ coercible (~> 1.0)
168
+ descendants_tracker (~> 0.0, >= 0.0.3)
169
+ equalizer (~> 0.0, >= 0.0.9)
170
+ yard (0.9.20)
171
+ yardstick (0.9.9)
172
+ yard (~> 0.8, >= 0.8.7.2)
173
+
174
+ PLATFORMS
175
+ ruby
176
+
177
+ DEPENDENCIES
178
+ devtools!
179
+ mprelude!
180
+ mutant (~> 0.8.24)
181
+ mutant-rspec (~> 0.8.24)
182
+
183
+ BUNDLED WITH
184
+ 2.0.1
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Markus Schirp
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # mprelude
2
+
3
+ Some foundational ruby data types.
data/lib/mprelude.rb ADDED
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abstract_type'
4
+ require 'adamantium'
5
+ require 'concord'
6
+
7
+ module MPrelude
8
+ module Functor
9
+ include AbstractType
10
+
11
+ abstract_method :fmap
12
+
13
+ private
14
+
15
+ # Raise error unless block is provided
16
+ #
17
+ # @raise [MissingBlockError]
18
+ # if no block is given
19
+ #
20
+ # @return [self]
21
+ def require_block
22
+ fail LocalJumpError unless block_given?
23
+ self
24
+ end
25
+ end # Functor
26
+
27
+ class Maybe
28
+ include(
29
+ AbstractType,
30
+ Adamantium::Flat,
31
+ Functor
32
+ )
33
+
34
+ class Nothing < self
35
+ instance = new
36
+
37
+ define_method(:new) { instance }
38
+
39
+ # Evaluate functor block
40
+ #
41
+ # @return [Maybe::Nothing]
42
+ def fmap(&block)
43
+ require_block(&block)
44
+ end
45
+
46
+ # Evaluate applicative block
47
+ #
48
+ # @return [Maybe::Nothing]
49
+ def apply(&block)
50
+ require_block(&block)
51
+ end
52
+ end # Nothing
53
+
54
+ class Just < self
55
+ include Concord.new(:value)
56
+
57
+ # Evalute functor block
58
+ #
59
+ # @return [Maybe::Just<Object>]
60
+ def fmap
61
+ Just.new(yield(value))
62
+ end
63
+
64
+ # Evalute applicative block
65
+ #
66
+ # @return [Maybe]
67
+ def apply
68
+ yield(value)
69
+ end
70
+ end # Just
71
+ end # Maybe
72
+
73
+ class Either
74
+ include(
75
+ AbstractType,
76
+ Adamantium::Flat,
77
+ Concord.new(:value),
78
+ Functor
79
+ )
80
+
81
+ # Execute block and wrap error in left
82
+ #
83
+ # @param [Class:Exception] error
84
+ #
85
+ # @return [Either<Exception, Object>]
86
+ def self.wrap_error(error)
87
+ Right.new(yield)
88
+ rescue error => exception
89
+ Left.new(exception)
90
+ end
91
+
92
+ class Left < self
93
+ # Evaluate functor block
94
+ #
95
+ # @return [Either::Left<Object>]
96
+ def fmap(&block)
97
+ require_block(&block)
98
+ end
99
+
100
+ # Evaluate applicative block
101
+ #
102
+ # @return [Either::Left<Object>]
103
+ def apply(&block)
104
+ require_block(&block)
105
+ end
106
+
107
+ # Unwrap value from left
108
+ #
109
+ # @return [Object]
110
+ def from_left
111
+ value
112
+ end
113
+
114
+ # Unwrap value from right
115
+ #
116
+ # @return [Object]
117
+ #
118
+ # rubocop:disable Style/GuardClause
119
+ def from_right
120
+ if block_given?
121
+ yield(value)
122
+ else
123
+ fail "Expected right value, got #{inspect}"
124
+ end
125
+ end
126
+ # rubocop:enable Style/GuardClause
127
+
128
+ # Map over left value
129
+ #
130
+ # @return [Either::Right<Object>]
131
+ def lmap
132
+ Left.new(yield(value))
133
+ end
134
+
135
+ # Evaluate left side of branch
136
+ #
137
+ # @param [#call] left
138
+ # @param [#call] _right
139
+ def either(left, _right)
140
+ left.call(value)
141
+ end
142
+ end # Left
143
+
144
+ class Right < self
145
+ # Evaluate functor block
146
+ #
147
+ # @return [Either::Right<Object>]
148
+ def fmap
149
+ Right.new(yield(value))
150
+ end
151
+
152
+ # Evaluate applicative block
153
+ #
154
+ # @return [Either<Object>]
155
+ def apply
156
+ yield(value)
157
+ end
158
+
159
+ # Unwrap value from left
160
+ #
161
+ # @return [Object]
162
+ #
163
+ # rubocop:disable Style/GuardClause
164
+ def from_left
165
+ if block_given?
166
+ yield(value)
167
+ else
168
+ fail "Expected left value, got #{inspect}"
169
+ end
170
+ end
171
+ # rubocop:enable Style/GuardClause
172
+
173
+ # Unwrap value from right
174
+ #
175
+ # @return [Object]
176
+ def from_right
177
+ value
178
+ end
179
+
180
+ # Map over left value
181
+ #
182
+ # @return [Either::Right<Object>]
183
+ def lmap(&block)
184
+ require_block(&block)
185
+ end
186
+
187
+ # Evaluate right side of branch
188
+ #
189
+ # @param [#call] _left
190
+ # @param [#call] right
191
+ def either(_left, right)
192
+ right.call(value)
193
+ end
194
+ end # Right
195
+ end # Either
196
+ end # MPrelude
data/mprelude.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'mprelude'
5
+ gem.version = '0.0.1'
6
+ gem.authors = ['Markus Schirp']
7
+ gem.email = ['mbj@schirp-dso.com']
8
+ gem.description = 'Minimal prelude alike classes'
9
+ gem.summary = 'Mostly an either type'
10
+ gem.homepage = 'https://github.com/mbj/mprelude-rb'
11
+ gem.licenses = 'MIT'
12
+
13
+ gem.require_paths = %w[lib]
14
+
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- spec/unit`.split("\n")
17
+ gem.extra_rdoc_files = %w[LICENSE]
18
+
19
+ gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
20
+ gem.add_runtime_dependency('adamantium', '~> 0.2.0')
21
+ gem.add_runtime_dependency('concord', '~> 0.1.5')
22
+ gem.add_runtime_dependency('equalizer', '~> 0.0.9')
23
+ gem.add_runtime_dependency('ice_nine', '~> 0.11.1')
24
+ gem.add_runtime_dependency('procto', '~> 0.0.2')
25
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mprelude'
4
+
5
+ RSpec.shared_examples 'no block evaluation' do
6
+ context 'with block' do
7
+ let(:block) { -> { fail } }
8
+
9
+ it 'does not evaluate block' do
10
+ apply
11
+ end
12
+ end
13
+ end
14
+
15
+ RSpec.shared_examples 'requires block' do
16
+ context 'without block' do
17
+ let(:block) { nil }
18
+
19
+ specify do
20
+ expect { apply }.to raise_error(LocalJumpError)
21
+ end
22
+ end
23
+ end
24
+
25
+ RSpec.shared_examples 'returns self' do
26
+ it 'returns self' do
27
+ expect(apply).to be(subject)
28
+ end
29
+ end
30
+
31
+ RSpec.shared_examples '#apply block evaluation' do
32
+ it 'evaluates block and returns its wrapped result' do
33
+ expect { expect(apply).to eql(block_result) }
34
+ .to change(yields, :to_a)
35
+ .from([])
36
+ .to([value])
37
+ end
38
+ end
39
+
40
+ RSpec.shared_examples 'Functor#fmap block evaluation' do
41
+ it 'evaluates block and returns its wrapped result' do
42
+ expect { expect(apply).to eql(described_class.new(block_result)) }
43
+ .to change(yields, :to_a)
44
+ .from([])
45
+ .to([value])
46
+ end
47
+ end
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MPrelude::Either do
4
+ describe '.wrap_error' do
5
+ def apply
6
+ described_class.wrap_error(error, &block)
7
+ end
8
+
9
+ let(:error) { TestError }
10
+
11
+ class TestError < RuntimeError; end
12
+
13
+ context 'when block returns' do
14
+ let(:value) { instance_double(Object, 'value') }
15
+ let(:block) { -> { value } }
16
+
17
+ it 'returns right wrapping block value' do
18
+ expect(apply).to eql(described_class::Right.new(value))
19
+ end
20
+ end
21
+
22
+ context 'when block raises' do
23
+ let(:exception) { error.new }
24
+ let(:block) { -> { fail exception } }
25
+
26
+ context 'with covered exception' do
27
+ it 'returns left wrapping exception' do
28
+ expect(apply).to eql(described_class::Left.new(exception))
29
+ end
30
+ end
31
+
32
+ context 'with uncovered exception' do
33
+ let(:exception) { StandardError.new }
34
+
35
+ it 'returns raises error' do
36
+ expect { apply }.to raise_error(StandardError)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ RSpec.describe MPrelude::Either::Left do
44
+ subject { described_class.new(value) }
45
+
46
+ let(:block_result) { instance_double(Object, 'block result') }
47
+ let(:value) { instance_double(Object, 'value') }
48
+ let(:yields) { [] }
49
+
50
+ let(:block) do
51
+ lambda do |value|
52
+ yields << value
53
+ block_result
54
+ end
55
+ end
56
+
57
+ class TestError < RuntimeError; end
58
+
59
+ describe '#fmap' do
60
+ def apply
61
+ subject.fmap(&block)
62
+ end
63
+
64
+ include_examples 'no block evaluation'
65
+ include_examples 'requires block'
66
+ include_examples 'returns self'
67
+ end
68
+
69
+ describe '#apply' do
70
+ def apply
71
+ subject.apply(&block)
72
+ end
73
+
74
+ include_examples 'no block evaluation'
75
+ include_examples 'requires block'
76
+ include_examples 'returns self'
77
+ end
78
+
79
+ describe '#from_left' do
80
+ def apply
81
+ subject.from_left(&block)
82
+ end
83
+
84
+ it 'returns left value' do
85
+ expect(apply).to be(value)
86
+ end
87
+
88
+ include_examples 'no block evaluation'
89
+ end
90
+
91
+ describe '#from_right' do
92
+ def apply
93
+ subject.from_right(&block)
94
+ end
95
+
96
+ context 'without block' do
97
+ let(:block) { nil }
98
+
99
+ it 'raises RuntimeError error' do
100
+ expect { apply }.to raise_error(
101
+ RuntimeError,
102
+ "Expected right value, got #{subject.inspect}"
103
+ )
104
+ end
105
+ end
106
+
107
+ context 'with block' do
108
+ let(:yields) { [] }
109
+ let(:block_return) { instance_double(Object, 'block-return') }
110
+
111
+ let(:block) do
112
+ lambda do |value|
113
+ yields << value
114
+ block_return
115
+ end
116
+ end
117
+
118
+ it 'calls block with left value' do
119
+ expect { apply }.to change(yields, :to_a).from([]).to([value])
120
+ end
121
+
122
+ it 'returns block value' do
123
+ expect(apply).to be(block_return)
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '#lmap' do
129
+ def apply
130
+ subject.lmap(&block)
131
+ end
132
+
133
+ include_examples 'requires block'
134
+ include_examples 'Functor#fmap block evaluation'
135
+ end
136
+
137
+ describe '#either' do
138
+ def apply
139
+ subject.either(block, -> { fail })
140
+ end
141
+
142
+ include_examples '#apply block evaluation'
143
+ end
144
+ end
145
+
146
+ RSpec.describe MPrelude::Either::Right do
147
+ subject { described_class.new(value) }
148
+
149
+ let(:block_result) { instance_double(Object, 'block result') }
150
+ let(:value) { instance_double(Object, 'value') }
151
+ let(:yields) { [] }
152
+
153
+ let(:block) do
154
+ lambda do |value|
155
+ yields << value
156
+ block_result
157
+ end
158
+ end
159
+
160
+ describe '#fmap' do
161
+ def apply
162
+ subject.fmap(&block)
163
+ end
164
+
165
+ include_examples 'requires block'
166
+ include_examples 'Functor#fmap block evaluation'
167
+ end
168
+
169
+ describe '#apply' do
170
+ def apply
171
+ subject.apply(&block)
172
+ end
173
+
174
+ include_examples 'requires block'
175
+ include_examples '#apply block evaluation'
176
+ end
177
+
178
+ describe '#from_left' do
179
+ def apply
180
+ subject.from_left(&block)
181
+ end
182
+
183
+ context 'without block' do
184
+ let(:block) { nil }
185
+
186
+ it 'raises RuntimeError error' do
187
+ expect { apply }.to raise_error(
188
+ RuntimeError,
189
+ "Expected left value, got #{subject.inspect}"
190
+ )
191
+ end
192
+ end
193
+
194
+ context 'with block' do
195
+ let(:yields) { [] }
196
+ let(:block_return) { instance_double(Object, 'block-return') }
197
+
198
+ let(:block) do
199
+ lambda do |value|
200
+ yields << value
201
+ block_return
202
+ end
203
+ end
204
+
205
+ it 'calls block with right value' do
206
+ expect { apply }.to change(yields, :to_a).from([]).to([value])
207
+ end
208
+
209
+ it 'returns block value' do
210
+ expect(apply).to be(block_return)
211
+ end
212
+ end
213
+ end
214
+
215
+ describe '#from_right' do
216
+ def apply
217
+ subject.from_right(&block)
218
+ end
219
+
220
+ it 'returns right value' do
221
+ expect(apply).to be(value)
222
+ end
223
+
224
+ include_examples 'no block evaluation'
225
+ end
226
+
227
+ describe '#lmap' do
228
+ def apply
229
+ subject.lmap(&block)
230
+ end
231
+
232
+ include_examples 'requires block'
233
+ include_examples 'no block evaluation'
234
+
235
+ it 'returns self' do
236
+ expect(apply).to be(subject)
237
+ end
238
+ end
239
+
240
+ describe '#either' do
241
+ def apply
242
+ subject.either(-> { fail }, block)
243
+ end
244
+
245
+ include_examples '#apply block evaluation'
246
+ end
247
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MPrelude::Maybe::Nothing do
4
+ subject { described_class.new }
5
+
6
+ let(:block) { -> {} }
7
+
8
+ describe '#fmap' do
9
+ def apply
10
+ subject.fmap(&block)
11
+ end
12
+
13
+ include_examples 'no block evaluation'
14
+ include_examples 'requires block'
15
+ include_examples 'returns self'
16
+ end
17
+
18
+ describe '#apply' do
19
+ def apply
20
+ subject.apply(&block)
21
+ end
22
+
23
+ include_examples 'no block evaluation'
24
+ include_examples 'requires block'
25
+ include_examples 'returns self'
26
+ end
27
+ end
28
+
29
+ RSpec.describe MPrelude::Maybe::Just do
30
+ subject { described_class.new(value) }
31
+
32
+ let(:block_result) { instance_double(Object, 'block result') }
33
+ let(:value) { instance_double(Object, 'value') }
34
+ let(:yields) { [] }
35
+
36
+ let(:block) do
37
+ lambda do |value|
38
+ yields << value
39
+ block_result
40
+ end
41
+ end
42
+
43
+ describe '#fmap' do
44
+ def apply
45
+ subject.fmap(&block)
46
+ end
47
+
48
+ include_examples 'requires block'
49
+ include_examples 'Functor#fmap block evaluation'
50
+ end
51
+
52
+ describe '#apply' do
53
+ def apply
54
+ subject.apply(&block)
55
+ end
56
+
57
+ include_examples 'requires block'
58
+ include_examples '#apply block evaluation'
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mprelude
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Markus Schirp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: abstract_type
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: adamantium
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: concord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: equalizer
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.9
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.9
69
+ - !ruby/object:Gem::Dependency
70
+ name: ice_nine
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.11.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.11.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: procto
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.2
97
+ description: Minimal prelude alike classes
98
+ email:
99
+ - mbj@schirp-dso.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files:
103
+ - LICENSE
104
+ files:
105
+ - ".rspec"
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE
109
+ - README.md
110
+ - lib/mprelude.rb
111
+ - mprelude.gemspec
112
+ - spec/spec_helper.rb
113
+ - spec/unit/mprelude/either_spec.rb
114
+ - spec/unit/mprelude/maybe_spec.rb
115
+ homepage: https://github.com/mbj/mprelude-rb
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubygems_version: 3.0.4
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Mostly an either type
138
+ test_files:
139
+ - spec/unit/mprelude/either_spec.rb
140
+ - spec/unit/mprelude/maybe_spec.rb