data.either 0.0.5 → 0.0.7

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: 059a7c25509fac130a6181614b89eea322e83b35
4
- data.tar.gz: 6130666ffaaf9a7992dc449f750bd71f1ee84fb3
3
+ metadata.gz: 08f4e5166ec1ad8d037c1242ad30dc3ea9e60e4c
4
+ data.tar.gz: f3fc3a10f5aede1bc5b949b664fe65979f619785
5
5
  SHA512:
6
- metadata.gz: 2ec33c7090e719ef4ed4b7ca8f7df3f0644054a162631641255a76714a44889c04f6c65184aebec2defb5740d32d423b17a68c59f3c150f6f9a031850eb004a5
7
- data.tar.gz: 9a3b0f5e6df569a984bae5d9256a7292a77a37bc710ec900d7e98ce97491e51a9ef1ffaa859075b64d2fb2fcc106428b2b6c1c393727ba253d6f96dc19645abc
6
+ metadata.gz: 5f31fccf30c2341d5bfce564060eddf90172613147663f52d48e6efd301b407ed0716d282c52c6097a7dd10e247d7de5e096b834b0760ea941f796004260c605
7
+ data.tar.gz: 980bb06448d07169db9c62a1ab80b27a33bca1d7ce56019c5447f28cfadfda392fd9dc2d53aebb925ec0dbcc4a8fe831773bea65b583a77b69c6dea58fe156bd
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+ module Control
3
+ module Functor
4
+ extend Helper
5
+ def map
6
+ end
7
+ end
8
+
9
+ module Monad
10
+ extend Helper
11
+ include Functor
12
+ def >=
13
+ raise '>= No defined'
14
+ end
15
+
16
+ alias_names([:flat_map], :>=)
17
+
18
+ def > k
19
+ self.>= { |_| k }
20
+ end
21
+ end
22
+
23
+ end
data/lib/data.either.rb CHANGED
@@ -1,9 +1,28 @@
1
- # a very simple Either
1
+ require 'control/monad'
2
+
3
+ # The `Either` union type represents values with two possibilities:
4
+ #
5
+ # `Either a b` is either `Left a` or `Right b`
2
6
  module Either
7
+ include Control::Monad
8
+
9
+ # Either only contain one value @v
10
+ # @return [Either]
3
11
  def initialize v
4
12
  @v = v
5
13
  end
6
14
 
15
+ # default `false`, should override in {Left} or {Right}
16
+ # @return [Boolean]
17
+ def left?
18
+ false
19
+ end
20
+ # (see #left?)
21
+ def right?
22
+ false
23
+ end
24
+
25
+ # get value `a` out from `Right a`, otherwise return `e`
7
26
  def get_or_else e
8
27
  case self
9
28
  when Right
@@ -13,7 +32,13 @@ module Either
13
32
  end
14
33
  end
15
34
 
16
- # Functor
35
+ # overide of Functor's `fmap`, apply function on `Right a`'s value `a`, do nothing if it's `Left e`
36
+ #
37
+ # ``` ruby
38
+ # Right.new(1).map {|x| x + 1} # => #<Right value=2>
39
+ # Left.new(1).map {|x| x + 1} # => #<Left value=1>
40
+ # ```
41
+ # @return [Either]
17
42
  def map
18
43
  case self
19
44
  when Right
@@ -22,9 +47,13 @@ module Either
22
47
  self
23
48
  end
24
49
  end
25
-
26
- alias :fmap :map
27
-
50
+ # the opposit of #map, apply function to `Left e`, do nothing if it's `Right a`
51
+ #
52
+ # ``` ruby
53
+ # Right.new(1).left_map {|x| x + 1} # => #<Right value=1>
54
+ # Left.new(1).left_map {|x| x + 1} # => #<Left value=2>
55
+ # ```
56
+ # @return [Either]
28
57
  def left_map
29
58
  case self
30
59
  when Left
@@ -34,6 +63,13 @@ module Either
34
63
  end
35
64
  end
36
65
 
66
+ # `bimap` accept 2 lambdas, if it's [Right], apply the 2nd lambda, otherwise apply to the first lambda
67
+ #
68
+ # ``` ruby
69
+ # Right.new(1).bimap ->(x){x-1}, ->(x){x+1} # => 2
70
+ # Left.new(1).bimap ->(x){x-1}, ->(x){x+1}) # => 0
71
+ # ```
72
+ # @return [Either]
37
73
  def bimap lfn, rfn
38
74
  case self
39
75
  when Right
@@ -43,8 +79,17 @@ module Either
43
79
  end
44
80
  end
45
81
 
46
- # Monad
47
- def bind
82
+ # it override {Monad#>=}, as Haskell's `>>=` method
83
+ # if it's {Right}, pass the value to #>='s block, and flat the result
84
+ # of the block.
85
+ #
86
+ # when it's {Left}, do nothing
87
+ # ``` ruby
88
+ # expect(Right.new(1).>= { |x| Left.new } ).to eq(Left.new)
89
+ # expect(Left.new(1).>= { |x| Left.new } ).to eq(Left.new(1))
90
+ # ```
91
+ # @return [Either]
92
+ def >=
48
93
  case self
49
94
  when Right
50
95
  yield @v
@@ -53,9 +98,26 @@ module Either
53
98
  end
54
99
  end
55
100
 
56
- alias :chain :bind
57
- alias :flat_map :bind
101
+ # similar to Scala's `match` for case class
102
+ #
103
+ # will pattern match the value out and pass to matched lambda
104
+ #
105
+ # ``` ruby
106
+ # Right.new(1).when({Right: ->x{x+1} }) # => 2
107
+ # Right.new(1).when({Left: ->x{x+1}) # => nil
108
+ # Right.new(1).when({Left: ->x{x+1}, _: ->x{x-1} }) # => 0
109
+ # ```
110
+ # @return [Either]
111
+ def when what
112
+ current_class = self.class.to_s.to_sym
113
+ if what.include? current_class
114
+ what[current_class].(@v)
115
+ elsif what.include? :_
116
+ what[:_].(@v)
117
+ end
118
+ end
58
119
 
120
+ # @return [String]
59
121
  def inspect
60
122
  case self
61
123
  when Left
@@ -64,13 +126,58 @@ module Either
64
126
  "#<Right value=#{@v}>"
65
127
  end
66
128
  end
129
+
130
+ # filter only {Right} value from List of {Either}
131
+ #
132
+ # ``` ruby
133
+ # Either.rights [Left.new(1),Right.new(5), Right.new(2)] # => [5, 2]
134
+ # ```
135
+ # @return [value]
136
+ def self.rights list_of_either
137
+ list_of_either.select(&:right?)
138
+ .map { |right| right.get_or_else(nil) }
139
+ end
140
+
141
+ # filter only {Left} value from List of {Either}
142
+ #
143
+ # ``` ruby
144
+ # Either.lefts [Left.new(1),Right.new(5), Right.new(2)] # => [1]
145
+ # ```
146
+ # @return [value]
147
+ def self.lefts list_of_either
148
+ list_of_either.select(&:left?)
149
+ .map { |left| left.when({Left: ->l{l}}) }
150
+ end
151
+
152
+ # partion a List of {Either} into a List of 2 List, one contains only {Left}, other contains only {Right}
153
+ #
154
+ # ``` ruby
155
+ # Either.partition [Left.new(1),Right.new(5), Right.new(2)] # => [[1],[5, 2]]
156
+ # ```
157
+ # @return [[l],[r]]
158
+ def self.partition list_of_either
159
+ list_of_either.inject([[],[]]) do |acc, x|
160
+ x.when({
161
+ Left: ->(l){acc[0].push(l)},
162
+ Right: ->(r){acc[1].push(r)}
163
+ })
164
+ acc
165
+ end
166
+ end
67
167
  end
68
168
 
169
+
69
170
  class Left
70
- include Either
171
+ include Either
71
172
  def initialize v=nil
72
173
  @v=v
73
174
  end
175
+
176
+ # always true
177
+ # @return [Boolean]
178
+ def left?
179
+ true
180
+ end
74
181
 
75
182
  def == other
76
183
  case other
@@ -84,6 +191,13 @@ end
84
191
 
85
192
  class Right
86
193
  include Either
194
+
195
+ # always true
196
+ # @return [Boolean]
197
+ def right?
198
+ true
199
+ end
200
+
87
201
  def == other
88
202
  case other
89
203
  when Right
data/lib/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Helper
2
+ def alias_names names, m
3
+ names.each do |name|
4
+ define_method(name) do |*args|
5
+ self.send(m, *args)
6
+ end
7
+ end
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data.either
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jichao Ouyang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-18 00:00:00.000000000 Z
11
+ date: 2016-08-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The Either Monad
14
14
  email: oyanglulu@gmail.com
@@ -16,7 +16,9 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
+ - lib/control/monad.rb
19
20
  - lib/data.either.rb
21
+ - lib/helper.rb
20
22
  homepage: https://github.com/jcouyang/cats.rb
21
23
  licenses:
22
24
  - MIT