module Either

The `Either` union type represents values with two possibilities:

`Either a b` is either `Left a` or `Right b`

Public Class Methods

lefts(list_of_either) click to toggle source

filter only {Left} value from List of {Either}

“` ruby Either.lefts [Left.new(1),Right.new(5), Right.new(2)] # => [1] “` @return [value]

# File lib/data.either.rb, line 205
def lefts(list_of_either)
  list_of_either.select(&:left?)
                .map { |left| left.when(Left: ->(l) { l }) }
end
new(v = nil) click to toggle source

Either only contain one value @v @return [Either]

# File lib/data.either.rb, line 27
def initialize(v = nil)
  @v = v
end
partition(list_of_either) click to toggle source

partion a List of {Either} into a List of 2 List, one contains only {Left}, other contains only {Right}

“` ruby Either.partition [Left.new(1),Right.new(5), Right.new(2)] # => [[1],[5, 2]] “` @return [[l],]

# File lib/data.either.rb, line 216
def partition(list_of_either)
  list_of_either.inject([[], []]) do |acc, x|
    x.when(Left: ->(l) { acc[0].push(l) },
           Right: ->(r) { acc[1].push(r) })
    acc
  end
end
rights(list_of_either) click to toggle source

filter only {Right} value from List of {Either}

“` ruby Either.rights [Left.new(1),Right.new(5), Right.new(2)] # => [5, 2] “` @return [value]

# File lib/data.either.rb, line 194
def rights(list_of_either)
  list_of_either.select(&:right?)
                .map { |right| right.get_or_else(nil) }
end
try() { || ... } click to toggle source

try something could raise exception, and wrap value into Right, exception into Left

@return [Either] “`ruby Either::try do

something_may_raise_error

end “`

# File lib/data.either.rb, line 19
def self.try
  Right.new(yield)
rescue => e
  Left.new(e)
end

Public Instance Methods

<=>(other) click to toggle source

comparable

# File lib/data.either.rb, line 166
def <=>(other)
  other =~ case self
           when Right
             { Right: ->(o) { @v <=> o },
               Left: ->(_) { 1 } }
           else
             { Right: ->(_) { -1 },
               Left: ->(o) { @v <=> o } }
           end
end
bimap(lfn, rfn) click to toggle source

`bimap` accept 2 lambdas, if it's [Right], apply the 2nd lambda, otherwise apply to the first lambda

“` ruby

Right.new(1).bimap ->(x){x-1}, ->(x){x+1} # => 2
Left.new(1).bimap ->(x){x-1}, ->(x){x+1}) # => 0

“` @return [Either]

# File lib/data.either.rb, line 106
def bimap(lfn, rfn)
  case self
  when Right
    Right.new(rfn.call(@v))
  else
    Left.new(lfn.call(@v))
  end
end
each(&block) click to toggle source
# File lib/data.either.rb, line 151
def each(&block)
  bimap(->(_) {}, &block)
end
flat_map() { |v| ... } click to toggle source

it override {Monad#flat_map}, as Haskell's `>flat_map` method if it's {Right}, pass the value to flat_map's block, and flat the result of the block.

when it's {Left}, do nothing “` ruby expect(Right.new(1).flat_map { |x| Left.new } ).to eq(Left.new) expect(Left.new(1).flat_map { |x| Left.new } ).to eq(Left.new(1)) “` @return [Either]

# File lib/data.either.rb, line 125
def flat_map
  case self
  when Right
    yield @v
  else
    self
  end
end
get_or_else(e) click to toggle source

get value `a` out from `Right a`, otherwise return `e` “`ruby Right.new(1).get_or_else(2) # => 1 Right.new(1) | 2 # => 1 “`

# File lib/data.either.rb, line 47
def get_or_else(e)
  case self
  when Right
    @v
  else
    e
  end
end
Also aliased as: |
inspect() click to toggle source

@return [String]

# File lib/data.either.rb, line 178
def inspect
  case self
  when Left
    "#<Left #{@v.inspect}>"
  else
    "#<Right #{@v.inspect}>"
  end
end
Also aliased as: to_s
left?() click to toggle source

default `false`, should override in {Left} or {Right} @return [Boolean]

# File lib/data.either.rb, line 33
def left?
  false
end
left_map() { |v)| ... } click to toggle source

the opposit of map, apply function to `Left e`, do nothing if it's `Right a`

“` ruby

Right.new(1).left_map {|x| x + 1} # => #<Right value=1>
Left.new(1).left_map {|x| x + 1} # => #<Left value=2>

“` @return [Either]

# File lib/data.either.rb, line 90
def left_map
  case self
  when Left
    Left.new(yield @v)
  else
    self
  end
end
map() { |v)| ... } click to toggle source

overide of Functor's `fmap`, apply function on `Right a`'s value `a`, do nothing if it's `Left e`

“` ruby

Right.new(1).map {|x| x + 1} # => #<Right value=2>
Left.new(1).map {|x| x + 1} # => #<Left value=1>

“` @return [Either]

# File lib/data.either.rb, line 74
def map
  case self
  when Right
    Right.new(yield @v)
  else
    self
  end
end
or_else(e) click to toggle source
# File lib/data.either.rb, line 58
def or_else(e)
  case self
  when Right

  else
    e
  end
end
right?() click to toggle source

(see left?)

# File lib/data.either.rb, line 38
def right?
  false
end
to_a() click to toggle source
# File lib/data.either.rb, line 155
def to_a
  case self
  when Right
    [@v]
  else
    []
  end
end
to_s()
Alias for: inspect
|(e)
Alias for: get_or_else