Module: Rumonade::Monad
- Includes:
- Enumerable
- Included in:
- Either::LeftProjection, Either::RightProjection, Option
- Defined in:
- lib/rumonade/monad.rb
Overview
Mix-in for common monad functionality dependent on implementation of monadic methods unit
and bind
Notes:
-
Classes should include this module AFTER defining the monadic methods
unit
andbind
-
When
Monad
is mixed into a class, if the class already contains methods in METHODS_TO_REPLACE, they will be renamed to add the suffix_without_monad
, and replaced with the method defined here which has the suffix_with_monad
Constant Summary collapse
- DEFAULT_METHODS_TO_REPLACE_WITH_MONAD =
Methods to replace when mixed in – unless class defines
METHODS_TO_REPLACE_WITH_MONAD
[:map, :flat_map, :flatten]
Class Method Summary collapse
-
.included(base) ⇒ Object
When mixed into a class, this callback is executed.
Instance Method Summary collapse
-
#can_flatten_in_monad? ⇒ Boolean
Returns
true
if #flatten_with_monad can call recursively on contained values members (eg. elements of an array). -
#each(lam = nil, &blk) ⇒ Object
Applies the given procedure to each element in this monad.
-
#flat_map_with_monad(lam = nil, &blk) ⇒ Object
Returns the results of applying the given function to each element in this monad.
-
#flatten_with_monad(depth = nil) ⇒ Object
Returns a monad whose elements are the ultimate (non-monadic) values contained in all nested monads.
-
#map_with_monad(lam = nil, &blk) ⇒ Object
Returns a monad whose elements are the results of applying the given function to each element in this monad.
-
#select(lam = nil, &blk) ⇒ Object
(also: #find_all)
Returns a monad whose elements are all those elements of this monad for which the given predicate returned true.
-
#shallow_flatten ⇒ Object
Returns a monad whose elements are the values contained in the first level of nested monads.
Class Method Details
.included(base) ⇒ Object
When mixed into a class, this callback is executed
15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/rumonade/monad.rb', line 15 def self.included(base) methods_to_replace = base::METHODS_TO_REPLACE_WITH_MONAD rescue DEFAULT_METHODS_TO_REPLACE_WITH_MONAD base.class_eval do # optimization: replace flat_map with an alias for bind, as they are identical alias_method :flat_map_with_monad, :bind methods_to_replace.each do |method_name| alias_method "#{method_name}_without_monad".to_sym, method_name if public_instance_methods.include? method_name alias_method method_name, "#{method_name}_with_monad".to_sym end end end |
Instance Method Details
#can_flatten_in_monad? ⇒ Boolean
Returns true
if #flatten_with_monad can call recursively on contained values members (eg. elements of an array).
NOTE: Is overridden in Hash.
99 100 101 |
# File 'lib/rumonade/monad.rb', line 99 def can_flatten_in_monad? true end |
#each(lam = nil, &blk) ⇒ Object
Applies the given procedure to each element in this monad
32 33 34 |
# File 'lib/rumonade/monad.rb', line 32 def each(lam = nil, &blk) bind { |v| (lam || blk).call(v) }; nil end |
#flat_map_with_monad(lam = nil, &blk) ⇒ Object
Returns the results of applying the given function to each element in this monad
NOTE: normally aliased as flat_map
when Monad
is mixed into a class
46 47 48 |
# File 'lib/rumonade/monad.rb', line 46 def flat_map_with_monad(lam = nil, &blk) bind(lam || blk) end |
#flatten_with_monad(depth = nil) ⇒ Object
Returns a monad whose elements are the ultimate (non-monadic) values contained in all nested monads
NOTE: normally aliased as flatten
when Monad
is mixed into a class
58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/rumonade/monad.rb', line 58 def flatten_with_monad(depth=nil) if depth.is_a? Integer depth.times.inject(self) { |e, _| e.shallow_flatten } else bind do |x| if x.is_a?(Monad) && x.can_flatten_in_monad? x.flatten_with_monad else self.class.unit(x) end end end end |
#map_with_monad(lam = nil, &blk) ⇒ Object
Returns a monad whose elements are the results of applying the given function to each element in this monad
NOTE: normally aliased as map
when Monad
is mixed into a class
39 40 41 |
# File 'lib/rumonade/monad.rb', line 39 def map_with_monad(lam = nil, &blk) bind { |v| self.class.unit((lam || blk).call(v)) } end |
#select(lam = nil, &blk) ⇒ Object Also known as: find_all
Returns a monad whose elements are all those elements of this monad for which the given predicate returned true
73 74 75 |
# File 'lib/rumonade/monad.rb', line 73 def select(lam = nil, &blk) bind { |x| (lam || blk).call(x) ? self.class.unit(x) : self.class.empty } end |
#shallow_flatten ⇒ Object
Returns a monad whose elements are the values contained in the first level of nested monads
This method is equivalent to the Scala flatten call (single-level flattening), whereas #flatten is in keeping with the native Ruby flatten calls (multiple-level flattening).
91 92 93 |
# File 'lib/rumonade/monad.rb', line 91 def shallow_flatten bind { |x| x.is_a?(Monad) ? x : self.class.unit(x) } end |