unsound 0.0.1 → 0.0.3

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 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