unsound 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d3d6412d4eda965925cd704816c57bf93db662b
4
- data.tar.gz: 58e1df47db4ad389b2ce8663123d874ed7e9445c
3
+ metadata.gz: 3c645e777dc983c390c247a59c5f2de02727346b
4
+ data.tar.gz: a316ea5ccba27d63f3a823344e7c256f36056f1c
5
5
  SHA512:
6
- metadata.gz: ee1992f01cf105fb33b2ab67e9264ce1922d612060b375cda2925c45e9266a6d0b2ee5c35aaeb38ff7f343010625012434a685608f8283bd412ea49b4e7f4552
7
- data.tar.gz: bb75c7554b7a173b1bb5588588ee534f46d0baeb05d2643e6f321455de19ff0b6a1c0c9ec20185576db87274b59e7607c488f7a1e82082b16e7e05e97caa39e1
6
+ metadata.gz: 0c2101d6baca2654803b9edcca62d5f2e7967a29114f252a7e1c7dbef763ffaa98c0bcaa00e042cf524014a04f13c46de7a7962f43e1857792a24f5921f221c0
7
+ data.tar.gz: 59979f8819eff54c06cab5d71eb3a8e27e2e555b1185a6721df4235d1512bd443affd17ed3a0a1adea2b6ae7609442ae0bf9e6feddd12c88e69cdc29e40477de
@@ -1,101 +1,2 @@
1
- require "abstract_type"
2
- require "concord"
3
-
4
- module Unsound
5
- module Data
6
- # @abstract
7
- class Either
8
- include AbstractType
9
- include Concord::Public.new(:value)
10
-
11
- # Wraps a raw value in a {Data::Right}
12
- #
13
- # @param value [Any] the value to wrap
14
- # @return [Data::Right]
15
- def self.of(value)
16
- Right.new(value)
17
- end
18
-
19
- abstract_method :fmap
20
- abstract_method :>>
21
-
22
- abstract_method :either
23
- abstract_method :and_then
24
- abstract_method :or_else
25
-
26
- private
27
-
28
- def of(value)
29
- self.class.of(value)
30
- end
31
- end
32
-
33
- class Left < Either
34
- # A Noop
35
- #
36
- # @return [Data::Left]
37
- def fmap(*)
38
- self
39
- end
40
-
41
- # A Noop
42
- #
43
- # @return [Data::Left]
44
- def >>(*)
45
- self
46
- end
47
- alias :and_then :>>
48
-
49
- # Chain another operation which can result in a {Data::Either}
50
- #
51
- # @param f[#call] the next operation
52
- # @return [Data::Left, Data::Right]
53
- def or_else(f = nil, &blk)
54
- (f || blk)[value]
55
- end
56
-
57
- # Call a function on the value in the {Data::Left}
58
- #
59
- # @param f [#call] a function capable of processing the value
60
- # @param _ [#call] a function that will never be called
61
- def either(f, _)
62
- f[value]
63
- end
64
- end
65
-
66
- class Right < Either
67
- # Apply a function to a value contained in a {Data::Right}
68
- #
69
- # @param f [#call] the function to apply
70
- # @return [Data::Right] the result of applying the function
71
- # wrapped in a {Data::Right}
72
- def fmap(f = nil, &blk)
73
- self >> Composition.compose(method(:of), (f || blk))
74
- end
75
-
76
- # Chain another operation which can result in a {Data::Either}
77
- #
78
- # @param f[#call] the next operation
79
- # @return [Data::Left, Data::Right]
80
- def >>(f = nil, &blk)
81
- (f || blk)[value]
82
- end
83
- alias :and_then :>>
84
-
85
- # A Noop
86
- #
87
- # @return [Data::Right]
88
- def or_else(*)
89
- self
90
- end
91
-
92
- # Call a function on the value in the {Data::Right}
93
- #
94
- # @param _ [#call] a function that will never be called
95
- # @param f [#call] a function capable of processing the value
96
- def either(_, f)
97
- f[value]
98
- end
99
- end
100
- end
101
- end
1
+ require_relative "data/either"
2
+ require_relative "data/maybe"
@@ -0,0 +1,101 @@
1
+ require "abstract_type"
2
+ require "concord"
3
+
4
+ module Unsound
5
+ module Data
6
+ # @abstract
7
+ class Either
8
+ include AbstractType
9
+ include Concord::Public.new(:value)
10
+
11
+ # Wraps a raw value in a {Data::Right}
12
+ #
13
+ # @param value [Any] the value to wrap
14
+ # @return [Data::Right]
15
+ def self.of(value)
16
+ Right.new(value)
17
+ end
18
+
19
+ abstract_method :fmap
20
+ abstract_method :>>
21
+
22
+ abstract_method :either
23
+ abstract_method :and_then
24
+ abstract_method :or_else
25
+
26
+ private
27
+
28
+ def of(value)
29
+ self.class.of(value)
30
+ end
31
+ end
32
+
33
+ class Left < Either
34
+ # A Noop
35
+ #
36
+ # @return [Data::Left]
37
+ def fmap(*)
38
+ self
39
+ end
40
+
41
+ # A Noop
42
+ #
43
+ # @return [Data::Left]
44
+ def >>(*)
45
+ self
46
+ end
47
+ alias :and_then :>>
48
+
49
+ # Chain another operation which can result in a {Data::Either}
50
+ #
51
+ # @param f[#call] the next operation
52
+ # @return [Data::Left, Data::Right]
53
+ def or_else(f = nil, &blk)
54
+ (f || blk)[value]
55
+ end
56
+
57
+ # Call a function on the value in the {Data::Left}
58
+ #
59
+ # @param f [#call] a function capable of processing the value
60
+ # @param _ [#call] a function that will never be called
61
+ def either(f, _)
62
+ f[value]
63
+ end
64
+ end
65
+
66
+ class Right < Either
67
+ # Apply a function to a value contained in a {Data::Right}
68
+ #
69
+ # @param f [#call] the function to apply
70
+ # @return [Data::Right] the result of applying the function
71
+ # wrapped in a {Data::Right}
72
+ def fmap(f = nil, &blk)
73
+ self >> Composition.compose(method(:of), (f || blk))
74
+ end
75
+
76
+ # Chain another operation which can result in a {Data::Either}
77
+ #
78
+ # @param f[#call] the next operation
79
+ # @return [Data::Left, Data::Right]
80
+ def >>(f = nil, &blk)
81
+ (f || blk)[value]
82
+ end
83
+ alias :and_then :>>
84
+
85
+ # A Noop
86
+ #
87
+ # @return [Data::Right]
88
+ def or_else(*)
89
+ self
90
+ end
91
+
92
+ # Call a function on the value in the {Data::Right}
93
+ #
94
+ # @param _ [#call] a function that will never be called
95
+ # @param f [#call] a function capable of processing the value
96
+ def either(_, f)
97
+ f[value]
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,87 @@
1
+ require "abstract_type"
2
+ require "equalizer"
3
+
4
+ module Unsound
5
+ module Data
6
+ # @abstract
7
+ class Maybe
8
+ include AbstractType
9
+
10
+ # Wraps a raw value in a {Data::Just}
11
+ #
12
+ # @param value [Any] the value to wrap
13
+ # @return [Data::Just]
14
+ def self.of(value)
15
+ Just.new(value)
16
+ end
17
+
18
+ abstract_method :fmap
19
+ abstract_method :>>
20
+
21
+ abstract_method :and_then
22
+ abstract_method :or_else
23
+
24
+ private
25
+
26
+ def of(value)
27
+ self.class.of(value)
28
+ end
29
+ end
30
+
31
+ class Nothing < Maybe
32
+ include Equalizer.new
33
+
34
+ # A Noop
35
+ #
36
+ # @return [Data::Nothing]
37
+ def fmap(*)
38
+ self
39
+ end
40
+
41
+ # A Noop
42
+ #
43
+ # @return [Data::Nothing]
44
+ def >>(*)
45
+ self
46
+ end
47
+ alias :and_then :>>
48
+
49
+ # Chain another operation which can result in a {Data::Maybe}
50
+ #
51
+ # @param f[#call] the next operation
52
+ # @return [Data::Nothing, Data::Just]
53
+ def or_else(f = nil, &blk)
54
+ (f || blk).call
55
+ end
56
+ end
57
+
58
+ class Just < Maybe
59
+ include Concord::Public.new(:value)
60
+
61
+ # Apply a function to a value contained in a {Data::Just}
62
+ #
63
+ # @param f [#call] the function to apply
64
+ # @return [Data::Just] the result of applying the function
65
+ # wrapped in a {Data::Just}
66
+ def fmap(f = nil, &blk)
67
+ self >> Composition.compose(method(:of), (f || blk))
68
+ end
69
+
70
+ # Chain another operation which can result in a {Data::Maybe}
71
+ #
72
+ # @param f[#call] the next operation
73
+ # @return [Data::Nothing, Data::Just]
74
+ def >>(f = nil, &blk)
75
+ (f || blk)[value]
76
+ end
77
+ alias :and_then :>>
78
+
79
+ # A Noop
80
+ #
81
+ # @return [Data::Just]
82
+ def or_else(*)
83
+ self
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,3 +1,3 @@
1
1
  module Unsound
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,92 @@
1
+ require "shared/functor_examples"
2
+ require "shared/monad_examples"
3
+
4
+ require "unsound"
5
+
6
+ RSpec.describe Unsound::Data::Maybe do
7
+ let(:value) { double(:value) }
8
+
9
+ let(:instances) do
10
+ [
11
+ Unsound::Data::Nothing.new,
12
+ Unsound::Data::Just.new(value)
13
+ ]
14
+ end
15
+
16
+ it "has an abstract base class" do
17
+ expect {
18
+ Unsound::Data::Maybe.new
19
+ }.to raise_error(NotImplementedError)
20
+ end
21
+
22
+ it_behaves_like "a Functor"
23
+
24
+ it_behaves_like "a Monad" do
25
+ let(:type) { Unsound::Data::Maybe }
26
+
27
+ specify { expect(type.of(value)).to eq(Unsound::Data::Just.new(value)) }
28
+ end
29
+
30
+ describe "#and_then" do
31
+ let(:and_then) do
32
+ ->(value) { Unsound::Data::Just.new([value, value]) }
33
+ end
34
+
35
+ context "a just" do
36
+ let(:just) { Unsound::Data::Just.new(value) }
37
+ let(:value) { double(:value) }
38
+
39
+ context "a function" do
40
+ it "applies the function over the value" do
41
+ expect(just.and_then(and_then)).to eq(and_then.call(value))
42
+ end
43
+ end
44
+
45
+ context "a block" do
46
+ it "applies the block over the value" do
47
+ expect(just.and_then(&and_then)).to eq(and_then.call(value))
48
+ end
49
+ end
50
+ end
51
+
52
+ context "a nothing" do
53
+ let(:nothing) { Unsound::Data::Nothing.new }
54
+ let(:error) { double(:error) }
55
+
56
+ it "is a noop returning self" do
57
+ expect(nothing.and_then(and_then)).to eq(nothing)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#or_else" do
63
+ let(:or_else) do
64
+ -> { Unsound::Data::Nothing.new }
65
+ end
66
+
67
+ context "a just" do
68
+ let(:just) { Unsound::Data::Right.new(value) }
69
+ let(:value) { double(:value) }
70
+
71
+ it "is a noop returning self" do
72
+ expect(just.or_else(or_else)).to eq(just)
73
+ end
74
+ end
75
+
76
+ context "a nothing" do
77
+ let(:nothing) { Unsound::Data::Nothing.new }
78
+
79
+ context "a function" do
80
+ it "calls the function" do
81
+ expect(nothing.or_else(or_else)).to eq(or_else.call)
82
+ end
83
+ end
84
+
85
+ context "a block" do
86
+ it "yields to the block" do
87
+ expect(nothing.or_else(&or_else)).to eq(or_else.call)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unsound
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Swan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-10 00:00:00.000000000 Z
11
+ date: 2015-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concord
@@ -86,6 +86,8 @@ files:
86
86
  - lib/unsound/composition.rb
87
87
  - lib/unsound/control.rb
88
88
  - lib/unsound/data.rb
89
+ - lib/unsound/data/either.rb
90
+ - lib/unsound/data/maybe.rb
89
91
  - lib/unsound/version.rb
90
92
  - spec/integration/try_spec.rb
91
93
  - spec/shared/functor_examples.rb
@@ -93,6 +95,7 @@ files:
93
95
  - spec/spec_helper.rb
94
96
  - spec/unit/unsound/control_spec.rb
95
97
  - spec/unit/unsound/data/either_spec.rb
98
+ - spec/unit/unsound/data/maybe_spec.rb
96
99
  - unsound.gemspec
97
100
  homepage: https://github.com/pdswan/unsound
98
101
  licenses:
@@ -125,3 +128,4 @@ test_files:
125
128
  - spec/spec_helper.rb
126
129
  - spec/unit/unsound/control_spec.rb
127
130
  - spec/unit/unsound/data/either_spec.rb
131
+ - spec/unit/unsound/data/maybe_spec.rb