Module: Fear::Either

Included in:
Left, Right
Defined in:
lib/fear/either.rb

Overview

Represents a value of one of two possible types (a disjoint union.) An instance of Either is either an instance of Left or Right.

A common use of Either is as an alternative to Option for dealing with possible missing values. In this usage, None is replaced with a Left which can contain useful information. Right takes the place of Some. Convention dictates that Left is used for failure and Right is used for Right.

For example, you could use Either<String, Fixnum> to select_or_else whether a received input is a String or an Fixnum.

Either is right-biased, which means that Right is assumed to be the default case to operate on. If it is Left, operations like #map, #flat_map, … return the Left value unchanged:


# @!method join_right

Joins an +Either+ through +Left+. This method requires
that the left side of this +Either+ is itself an
+Either+ type.
@note This method, and +join_right+, are analogous to +Option#flatten+
@return [Either]
@raise [TypeError] if it does not contain +Either+.
@example
  Left(Right("flower")).join_left #=> Right("flower")
  Left(Left(12)).join_left        #=> Left(12)
  Right("daisy").join_left        #=> Right("daisy")
  Right(Left("daisy")).join_left  #=> Right(Left("daisy"))

Examples:

in = Readline.readline('Type Either a string or an Int: ', true)
result = begin
  Right(Integer(in))
rescue ArgumentError
  Left(in)
end

puts(
  result.reduce(
    -> (x) { "You passed me the Int: #{x}, which I will increment. #{x} + 1 = #{x+1}" },
    -> (x) { "You passed me the String: #{x}" }
  )
)

See Also:

Defined Under Namespace

Modules: Mixin

Instance Method Summary collapse

Instance Method Details

#any? {|value| ... } ⇒ Boolean

Returns false if Left or returns the result of the application of the given predicate to the Right value.

Examples:

Right(12).any?( |v| v > 10)         #=> true
Right(7).any?( |v| v > 10)          #=> false
Left('undefined').any?( |v| v > 10) #=> false

Yield Parameters:

  • value (any)

Yield Returns:

  • (Boolean)

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#each {|value| ... } ⇒ Option

Performs the given block if this is a Right.

Examples:

Right(17).each do |value|
  puts value
end #=> prints 17

Left('undefined').each do |value|
  puts value
end #=> does nothing

Yield Parameters:

  • value (any)

Yield Returns:

  • (void)

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#flat_map {|value| ... } ⇒ Option

Returns the given block applied to the value from this Right or returns this if this is a Left.

Examples:

Right(42).flat_map { |v| Right(v/2) }         #=> Right(21)
Left('undefined').flat_map { |v| Right(v/2) } #=> Left('undefined')

Yield Parameters:

  • value (any)

Yield Returns:

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#get_or_else(&default) ⇒ any #get_or_else(default) ⇒ any

Returns the value from this Right or evaluates the given default argument if this is a Left.

Overloads:

  • #get_or_else(&default) ⇒ any

    Examples:

    Right(42).get_or_else { 24/2 }         #=> 42
    Left('undefined').get_or_else { 24/2 } #=> 12
    

    Yield Returns:

    • (any)

    Returns:

    • (any)
  • #get_or_else(default) ⇒ any

    Examples:

    Right(42).get_or_else(12)         #=> 42
    Left('undefined').get_or_else(12) #=> 12
    

    Returns:

    • (any)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#include?(other_value) ⇒ Boolean

Returns true if Right has an element that is equal (as determined by ==) to other_value, false otherwise.

Examples:

Right(17).include?(17)         #=> true
Right(17).include?(7)          #=> false
Left('undefined').include?(17) #=> false

Parameters:

  • (any)

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#initialize(value) ⇒ Object



237
238
239
# File 'lib/fear/either.rb', line 237

def initialize(value)
  @value = value
end

#join_rightEither

Note:

This method, and join_left, are analogous to Option#flatten

Joins an Either through Right. This method requires that the right side of this Either is itself an Either type.

Examples:

Right(Right(12)).join_right      #=> Right(12)
Right(Left("flower")).join_right #=> Left("flower")
Left("flower").join_right        #=> Left("flower")
Left(Right("flower")).join_right #=> Left(Right("flower"))

Returns:

Raises:

  • (TypeError)

    if it does not contain Either.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#left?Boolean

Note:

this method is also aliased as #failure?

Returns true if this is a Left, false otherwise.

Examples:

Right(42).left?   #=> false
Left('err').left? #=> true

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#map {|value| ... } ⇒ Object

Maps the given block to the value from this Right or returns this if this is a Left.

Examples:

Right(42).map { |v| v/2 }          #=> Right(21)
Left('undefined').map { |v| v/2 }  #=> Left('undefined')

Yield Parameters:

  • value (any)

Yield Returns:

  • (any)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#reduce(reduce_left, reduce_right) ⇒ any

Applies reduce_left if this is a Left or reduce_right if this is a Right.

Examples:

result = possibly_failing_operation()
log(
  result.reduce(
    ->(ex) { "Operation failed with #{ex}" },
    ->(v) { "Operation produced value: #{v}" },
  )
)

Parameters:

  • reduce_left (Proc)

    the Proc to apply if this is a Left

  • reduce_right (Proc)

    the Proc to apply if this is a Right

Returns:

  • (any)

    the results of applying the Proc



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#reject {|value| ... } ⇒ Either

Returns Left of value if the given predicate holds for the right value, otherwise, returns Right.

Examples:

Right(12).reject(&:even?) #=> Left(12)
Right(7).reject(&:even?)  #=> Right(7)
Left(12).reject(&:even?)  #=> Left(12)
Left(7).reject(&:even?)   #=> Left(7)

Yield Parameters:

  • value (Object)

Yield Returns:

  • (Boolean)

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#right?Boolean

Note:

this method is also aliased as #success?

Returns true if this is a Right, false otherwise.

Examples:

Right(42).right?   #=> true
Left('err').right? #=> false

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#select {|value| ... } ⇒ Either

Returns Left of value if the given predicate does not hold for the right value, otherwise, returns Right.

Examples:

Right(12).select(&:even?) #=> Right(12)
Right(7).select(&:even?)  #=> Left(7)
Left(12).select(&:even?)  #=> Left(12)
Left(7).select(&:even?)   #=> Left(7)

Yield Parameters:

  • value (Object)

Yield Returns:

  • (Boolean)

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#select_or_else(default) {|value| ... } ⇒ Either

Returns Left of the default if the given predicate does not hold for the right value, otherwise, returns Right.

Examples:

Right(12).select_or_else(-1, &:even?)       #=> Right(12)
Right(7).select_or_else(-1, &:even?)        #=> Left(-1)
Left(12).select_or_else(-1, &:even?)        #=> Left(-1)
Left(12).select_or_else(-> { -1 }, &:even?) #=> Left(-1)

Parameters:

  • default (Object, Proc)

Yield Parameters:

  • value (Object)

Yield Returns:

  • (Boolean)

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#swapEither

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

Examples:

Left('left').swap   #=> Right('left')
Right('right').swap #=> Light('left')

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#to_aArray

Returns an Array containing the Right value or an empty Array if this is a Left.

Examples:

Right(42).to_a          #=> [21]
Left('undefined').to_a  #=> []

Returns:

  • (Array)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end

#to_optionOption

Returns an Some containing the Right value or a None if this is a Left.

Examples:

Right(42).to_option          #=> Some(21)
Left('undefined').to_option  #=> None()

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/fear/either.rb', line 224

module Either
  include Dry::Equalizer(:value)

  # @private
  def left_class
    Left
  end

  # @private
  def right_class
    Right
  end

  def initialize(value)
    @value = value
  end

  attr_reader :value
  protected :value

  # Include this mixin to access convenient factory methods.
  # @example
  #   include Fear::Either::Mixin
  #
  #   Right('flower') #=> #<Fear::Right value='flower'>
  #   Left('beaf')    #=> #<Fear::Legt value='beaf'>
  #
  module Mixin
    # @param [any]
    # @return [Left]
    def Left(value)
      Left.new(value)
    end

    # @param [any]
    # @return [Right]
    def Right(value)
      Right.new(value)
    end
  end
end