data.either 0.0.5 → 0.0.7

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