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 +7 -0
- data/.rspec +5 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +184 -0
- data/LICENSE +20 -0
- data/README.md +3 -0
- data/lib/mprelude.rb +196 -0
- data/mprelude.gemspec +25 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/unit/mprelude/either_spec.rb +247 -0
- data/spec/unit/mprelude/maybe_spec.rb +60 -0
- metadata +140 -0
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
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
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
|
data/spec/spec_helper.rb
ADDED
|
@@ -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
|