Class: Dry::Monads::List
- Inherits:
-
Object
- Object
- Dry::Monads::List
- Includes:
- Transformer
- Defined in:
- lib/dry/monads/list.rb
Overview
The List monad.
Defined Under Namespace
Modules: Mixin Classes: ListBuilder
Instance Attribute Summary collapse
-
#type ⇒ Object
readonly
Internal array value.
-
#value ⇒ Object
(also: #to_ary)
readonly
Internal array value.
Class Method Summary collapse
-
.[](*values) ⇒ List
Builds a list.
-
.coerce(value, type = nil) ⇒ List
Coerces a value to a list.
-
.pure(value = Undefined, type = nil, &block) ⇒ List
Wraps a value with a list.
-
.unfold(state, type = nil) ⇒ List
Iteratively builds a new list from a block returning Maybe values.
Instance Method Summary collapse
-
#+(other) ⇒ List
Concatenates two lists.
-
#apply(list = Undefined) ⇒ List
Applies the stored functions to the elements of the given list.
-
#bind(*args) ⇒ List
Lifts a block/proc and runs it against each member of the list.
-
#collect ⇒ List
Iterates over the list and collects Some values.
-
#deconstruct ⇒ Object
private
Pattern matching.
-
#empty? ⇒ TrueClass, FalseClass
Whether the list is empty.
-
#filter ⇒ List
(also: #select)
Filters elements with a block.
-
#first ⇒ Object
Returns the first element.
-
#fmap(*args) ⇒ List
Maps a block over the list.
-
#fold_left(initial) ⇒ Object
(also: #foldl, #reduce)
Folds the list from the left.
-
#fold_right(initial) ⇒ Object
(also: #foldr)
Folds the list from the right.
-
#head ⇒ Maybe<Object>
Returns the first element wrapped with a ‘Maybe`.
-
#initialize(value, type = nil) ⇒ List
constructor
private
A new instance of List.
-
#inspect ⇒ String
(also: #to_s)
Returns a string representation of the list.
-
#last ⇒ Object
Returns the last element.
-
#map(&block) ⇒ List, Enumerator
Maps a block over the list.
-
#monad ⇒ Monad
Returns the List monad.
-
#reverse ⇒ List
Reverses the list.
-
#size ⇒ Integer
List size.
-
#sort ⇒ List
Sorts the list.
-
#tail ⇒ List
Returns list’s tail.
-
#to_monad ⇒ List
Returns self.
-
#traverse(proc = nil, &block) ⇒ Monad
Traverses the list with a block (or without it).
-
#typed(type = nil) ⇒ List
Turns the list into a typed one.
-
#typed? ⇒ Boolean
Whether the list is types.
Methods included from Transformer
Constructor Details
#initialize(value, type = nil) ⇒ List
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of List.
83 84 85 86 |
# File 'lib/dry/monads/list.rb', line 83 def initialize(value, type = nil) @value = value @type = type end |
Instance Attribute Details
#type ⇒ Object (readonly)
Internal array value
80 81 82 |
# File 'lib/dry/monads/list.rb', line 80 def type @type end |
#value ⇒ Object (readonly) Also known as: to_ary
Internal array value
80 81 82 |
# File 'lib/dry/monads/list.rb', line 80 def value @value end |
Class Method Details
.[](*values) ⇒ List
Builds a list.
12 |
# File 'lib/dry/monads/list.rb', line 12 def [](*values) = new(values) |
.coerce(value, type = nil) ⇒ List
Coerces a value to a list. ‘nil` will be coerced to an empty list.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/dry/monads/list.rb', line 19 def coerce(value, type = nil) if value.nil? List.new([], type) elsif value.respond_to?(:to_ary) values = value.to_ary if !values.empty? && type.nil? && values[0].respond_to?(:monad) List.new(values, values[0].monad) else List.new(values, type) end else raise TypeError, "Can't coerce #{value.inspect} to List" end end |
.pure(value = Undefined, type = nil, &block) ⇒ List
Wraps a value with a list.
39 40 41 42 43 44 45 46 47 |
# File 'lib/dry/monads/list.rb', line 39 def pure(value = Undefined, type = nil, &block) if value.equal?(Undefined) new([block]) elsif block new([block], value) else new([value], type) end end |
.unfold(state, type = nil) ⇒ List
Iteratively builds a new list from a block returning Maybe values
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/dry/monads/list.rb', line 56 def unfold(state, type = nil) xs = [] loop do m = yield(state) if m.some? state, x = m.value! xs << x else break end end new(xs, type) end |
Instance Method Details
#+(other) ⇒ List
Concatenates two lists.
145 |
# File 'lib/dry/monads/list.rb', line 145 def +(other) = List.new(to_ary + other.to_ary) |
#apply(list = Undefined) ⇒ List
Applies the stored functions to the elements of the given list.
282 283 284 285 |
# File 'lib/dry/monads/list.rb', line 282 def apply(list = Undefined, &) v = Undefined.default(list, &) fmap(Curry).bind { |f| v.fmap { f.(_1) } } end |
#bind(*args) ⇒ List
Lifts a block/proc and runs it against each member of the list. The block must return a value coercible to a list. As in other monads if no block given the first argument will be treated as callable and used instead.
99 100 101 102 103 104 105 106 |
# File 'lib/dry/monads/list.rb', line 99 def bind(*args) if block_given? List.coerce(value.map { yield(_1, *args) }.reduce([], &:+)) else obj, *rest = args List.coerce(value.map { obj.(_1, *rest) }.reduce([], &:+)) end end |
#collect ⇒ List
Iterates over the list and collects Some values.
315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/dry/monads/list.rb', line 315 def collect if block_given? collected = value.each_with_object([]) do |x, ys| y = yield(x) ys << y.value! if y.some? end List.new(collected) else Enumerator.new do |g| value.each { g << _1.value! if _1.some? } end end end |
#deconstruct ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Pattern matching
340 |
# File 'lib/dry/monads/list.rb', line 340 def deconstruct = value |
#empty? ⇒ TrueClass, FalseClass
Whether the list is empty.
193 |
# File 'lib/dry/monads/list.rb', line 193 def empty? = value.empty? |
#filter ⇒ List Also known as: select
Filters elements with a block
203 |
# File 'lib/dry/monads/list.rb', line 203 def filter(&) = coerce(value.select(&)) |
#first ⇒ Object
Returns the first element.
166 |
# File 'lib/dry/monads/list.rb', line 166 def first = value.first |
#fmap(*args) ⇒ List
Maps a block over the list. Acts as ‘Array#map`. As in other monads if no block given the first argument will be treated as callable and used instead.
117 118 119 120 121 122 123 124 |
# File 'lib/dry/monads/list.rb', line 117 def fmap(*args) if block_given? List.new(value.map { yield(_1, *args) }) else obj, *rest = args List.new(value.map { obj.(_1, *rest) }) end end |
#fold_left(initial) ⇒ Object Also known as: foldl, reduce
Folds the list from the left.
177 |
# File 'lib/dry/monads/list.rb', line 177 def fold_left(initial, &) = value.reduce(initial, &) |
#fold_right(initial) ⇒ Object Also known as: foldr
Folds the list from the right.
185 186 187 |
# File 'lib/dry/monads/list.rb', line 185 def fold_right(initial) value.reverse.reduce(initial) { |a, b| yield(b, a) } end |
#head ⇒ Maybe<Object>
Returns the first element wrapped with a ‘Maybe`.
219 |
# File 'lib/dry/monads/list.rb', line 219 def head = Monads::Maybe.coerce(value.first) |
#inspect ⇒ String Also known as: to_s
Returns a string representation of the list.
153 154 155 156 |
# File 'lib/dry/monads/list.rb', line 153 def inspect type_ann = typed? ? "<#{type.name.split("::").last}>" : "" "List#{type_ann}#{value.inspect}" end |
#last ⇒ Object
Returns the last element.
171 |
# File 'lib/dry/monads/list.rb', line 171 def last = value.last |
#map(&block) ⇒ List, Enumerator
Maps a block over the list. Acts as ‘Array#map`. If called without a block, this method returns an enumerator, not a List
130 131 132 133 134 135 136 |
# File 'lib/dry/monads/list.rb', line 130 def map(&block) if block_given? fmap(block) else value.map end end |
#monad ⇒ Monad
Returns the List monad.
290 |
# File 'lib/dry/monads/list.rb', line 290 def monad = List |
#reverse ⇒ List
Reverses the list.
214 |
# File 'lib/dry/monads/list.rb', line 214 def reverse = coerce(value.reverse) |
#size ⇒ Integer
List size.
209 |
# File 'lib/dry/monads/list.rb', line 209 def size = value.size |
#sort ⇒ List
Sorts the list.
198 |
# File 'lib/dry/monads/list.rb', line 198 def sort = coerce(value.sort) |
#tail ⇒ List
Returns list’s tail.
224 |
# File 'lib/dry/monads/list.rb', line 224 def tail = coerce(value.drop(1)) |
#traverse(proc = nil, &block) ⇒ Monad
Traverses the list with a block (or without it). This methods “flips” List structure with the given monad (obtained from the type). Note that traversing requires the list to be typed. Also if a block given, its returning type must be equal list’s type.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/dry/monads/list.rb', line 263 def traverse(proc = nil, &block) unless typed? raise StandardError, "Cannot traverse an untyped list" end cons = type.pure { |list, i| list + List.pure(i) } with = proc || block || Traverse[type] foldl(type.pure(EMPTY)) do |acc, el| cons .apply(acc) .apply { with.(el) } end end |
#typed(type = nil) ⇒ List
Turns the list into a typed one. Type is required for some operations like .traverse.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/dry/monads/list.rb', line 231 def typed(type = nil) if type.nil? if size.zero? raise ArgumentError, "Cannot infer a monad for an empty list" else self.class.warn( "Automatic monad inference is deprecated, pass a type explicitly " \ "or use a predefined constant, e.g. List::Result\n" \ "#{caller.find { _1 !~ %r{(lib/dry/monads)|(gems)} }}" ) self.class.new(value, value[0].monad) end else self.class.new(value, type) end end |
#typed? ⇒ Boolean
Whether the list is types
251 |
# File 'lib/dry/monads/list.rb', line 251 def typed? = !type.nil? |