Class: Rumonade::Either Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/rumonade/either.rb,
lib/rumonade/either.rb

Overview

This class is abstract.

Represents a value of one of two possible types (a disjoint union). The data constructors Left and Right represent the two possible values. The Either type is often used as an alternative to Option where Left represents failure (by convention) and Right is akin to Some.

This implementation of Either also contains ideas from the Validation class in the scalaz library.

Direct Known Subclasses

Left, Right

Defined Under Namespace

Classes: LeftProjection, RightProjection

Constant Summary collapse

DEFAULT_CONCAT =

Default concatenation function used by #+

lambda { |a,b| a + b }

Instance Method Summary collapse

Instance Method Details

#+(other, opts = {}) {|right_value| ... } ⇒ Either Also known as: concat

Returns if both are Right, returns Right with right_value‘s concatenated, otherwise a Left with left_value’s concatenated.

Options Hash (opts):

  • :concat_left (Proc) — default: DEFAULT_CONCAT

    The function to concatenate Left values

  • :concat_right (Proc) — default: DEFAULT_CONCAT

    the function to concatenate Right values

Yields:

  • (right_value)

    optional block to transform concatenated Right values

Yield Parameters:

  • right_values (Object)

    the concatenated Right values yielded to optional block



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rumonade/either.rb', line 62

def +(other, opts = {})
  opts = { :concat_left  => DEFAULT_CONCAT, :concat_right => DEFAULT_CONCAT }.merge(opts)
  result =
    case self
      when Left
        case other
          when Left then Left(opts[:concat_left].call(self.left_value, other.left_value))
          when Right then Left(self.left_value)
        end
      when Right
        case other
          when Left then Left(other.left_value)
          when Right then Right(opts[:concat_right].call(self.right_value, other.right_value))
        end
    end
  if block_given? then result.right.map { |right_values| yield right_values } else result end
end

#fold(function_of_left_value, function_of_right_value) ⇒ Object



37
38
39
# File 'lib/rumonade/either.rb', line 37

def fold(function_of_left_value, function_of_right_value)
  if left? then function_of_left_value.call(left_value) else function_of_right_value.call(right_value) end
end

#leftLeftProjection



42
43
44
# File 'lib/rumonade/either.rb', line 42

def left
  LeftProjection.new(self)
end

#left?Boolean



20
21
22
# File 'lib/rumonade/either.rb', line 20

def left?
  is_a?(Left)
end

#lift(monad_class) ⇒ Either



90
91
92
# File 'lib/rumonade/either.rb', line 90

def lift(monad_class)
  fold(lambda {|l| Left(monad_class.unit(l)) }, lambda {|r| Right(monad_class.unit(r))})
end

#lift_to_aEither



83
84
85
# File 'lib/rumonade/either.rb', line 83

def lift_to_a
  lift(Array)
end

#rightRightProjection



47
48
49
# File 'lib/rumonade/either.rb', line 47

def right
  RightProjection.new(self)
end

#right?Boolean



25
26
27
# File 'lib/rumonade/either.rb', line 25

def right?
  is_a?(Right)
end

#swapBoolean



30
31
32
# File 'lib/rumonade/either.rb', line 30

def swap
  if left? then Right(left_value) else Left(right_value) end
end