lib/rumonade/either.rb in rumonade-0.2.2 vs lib/rumonade/either.rb in rumonade-0.3.0

- old
+ new

@@ -42,19 +42,52 @@ # @return [RightProjection] Projects this Either as a Right. def right RightProjection.new(self) end - # @param [Either] other the either to combine with - # @return [Either] Returns a +Left+ with all Left values (if any), otherwise a +Right+ with all Right values - def +(other) - if [self, other].any?(&:left?) - Left([self, other].map { |either| either.left.to_opt }.flatten) - else - Right([self, other].map { |either| either.right.to_opt }.flatten) - end + # Default concatenation function used by {#+} + DEFAULT_CONCAT = lambda { |a,b| a + b } + + # @param [Either] other the other +Either+ to concatenate + # @param [Hash] opts the options to concatenate with + # @option opts [Proc] :concat_left (DEFAULT_CONCAT) The function to concatenate +Left+ values + # @option opts [Proc] :concat_right (DEFAULT_CONCAT) the function to concatenate +Right+ values + # @yield [right_value] optional block to transform concatenated +Right+ values + # @yieldparam [Object] right_values the concatenated +Right+ values yielded to optional block + # @return [Either] if both are +Right+, returns +Right+ with +right_value+'s concatenated, + # otherwise a +Left+ with +left_value+'s concatenated + 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 + alias_method :concat, :+ + + # @return [Either] returns an +Either+ of the same type, with the +left_value+ or +right_value+ + # lifted into an +Array+ + def lift_to_a + lift(Array) + end + + # @param [#unit] monad_class the {Monad} to lift the +Left+ or +Right+ value into + # @return [Either] returns an +Either+of the same type, with the +left_value+ or +right_value+ + # lifted into +monad_class+ + def lift(monad_class) + fold(lambda {|l| Left(monad_class.unit(l)) }, lambda {|r| Right(monad_class.unit(r))}) + end end # The left side of the disjoint union, as opposed to the Right side. class Left < Either # @param left_value the value to store in a +Left+, usually representing a failure result @@ -72,10 +105,15 @@ # @return [String] Returns a +String+ representation of this object. def to_s "Left(#{left_value})" end + + # @return [String] Returns a +String+ containing a human-readable representation of this object. + def inspect + "Left(#{left_value.inspect})" + end end # The right side of the disjoint union, as opposed to the Left side. class Right < Either # @param right_value the value to store in a +Right+, usually representing a success result @@ -93,10 +131,15 @@ # @return [String] Returns a +String+ representation of this object. def to_s "Right(#{right_value})" end + + # @return [String] Returns a +String+ containing a human-readable representation of this object. + def inspect + "Right(#{right_value.inspect})" + end end # @param (see Left#initialize) # @return [Left] def Left(left_value) @@ -182,10 +225,15 @@ # @return [String] Returns a +String+ representation of this object. def to_s "LeftProjection(#{either_value})" end + + # @return [String] Returns a +String+ containing a human-readable representation of this object. + def inspect + "LeftProjection(#{either_value.inspect})" + end end # Projects an Either into a Right. class RightProjection class << self @@ -257,9 +305,14 @@ end # @return [String] Returns a +String+ representation of this object. def to_s "RightProjection(#{either_value})" + end + + # @return [String] Returns a +String+ containing a human-readable representation of this object. + def inspect + "RightProjection(#{either_value.inspect})" end end end end \ No newline at end of file