mprelude 0.0.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 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