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.

Parameters:

  • other (Either)

    the other Either to concatenate

  • opts (Hash) (defaults to: {})

    the options to concatenate with

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

Returns:

  • (Either)

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



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

Returns the results of applying the function

Parameters:

  • function_of_left_value (Proc)

    the function to apply if this is a Left

  • function_of_right_value (Proc)

    the function to apply if this is a Right

Returns:

  • Returns the results of applying the function



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

Returns Projects this Either as a Left.

Returns:



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

def left
  LeftProjection.new(self)
end

#left?Boolean

Returns true if this is a Left, false otherwise.

Returns:

  • (Boolean)

    Returns true if this is a Left, false otherwise.



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

def left?
  is_a?(Left)
end

#lift(monad_class) ⇒ Either

Returns an Eitherof the same type, with the left_value or right_value lifted into monad_class

Parameters:

  • monad_class (#unit)

    the Monad to lift the Left or Right value into

Returns:

  • (Either)

    returns an Eitherof the same type, with the left_value or right_value lifted into monad_class



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

Returns an Either of the same type, with the left_value or right_value lifted into an Array

Returns:

  • (Either)

    returns an Either of the same type, with the left_value or right_value lifted into an Array



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

def lift_to_a
  lift(Array)
end

#rightRightProjection

Returns Projects this Either as a Right.

Returns:



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

def right
  RightProjection.new(self)
end

#right?Boolean

Returns true if this is a Right, false otherwise.

Returns:

  • (Boolean)

    Returns true if this is a Right, false otherwise.



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

def right?
  is_a?(Right)
end

#swapBoolean

Returns If this is a Left, then return the left value in Right or vice versa.

Returns:

  • (Boolean)

    If this is a Left, then return the left value in Right or vice versa.



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

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