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, &block) ⇒ 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(&block) ⇒ 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, &block) ⇒ 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.
85 86 87 88 |
# File 'lib/dry/monads/list.rb', line 85 def initialize(value, type = nil) @value = value @type = type end |
Instance Attribute Details
#type ⇒ Object (readonly)
Internal array value
82 83 84 |
# File 'lib/dry/monads/list.rb', line 82 def type @type end |
#value ⇒ Object (readonly) Also known as: to_ary
Internal array value
82 83 84 |
# File 'lib/dry/monads/list.rb', line 82 def value @value end |
Class Method Details
.[](*values) ⇒ List
Builds a list.
12 13 14 |
# File 'lib/dry/monads/list.rb', line 12 def [](*values) new(values) end |
.coerce(value, type = nil) ⇒ List
Coerces a value to a list. ‘nil` will be coerced to an empty list.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/dry/monads/list.rb', line 21 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.
41 42 43 44 45 46 47 48 49 |
# File 'lib/dry/monads/list.rb', line 41 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
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/dry/monads/list.rb', line 58 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.
147 148 149 |
# File 'lib/dry/monads/list.rb', line 147 def +(other) List.new(to_ary + other.to_ary) end |
#apply(list = Undefined, &block) ⇒ List
Applies the stored functions to the elements of the given list.
308 309 310 311 |
# File 'lib/dry/monads/list.rb', line 308 def apply(list = Undefined, &block) v = Undefined.default(list, &block) 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.
101 102 103 104 105 106 107 108 |
# File 'lib/dry/monads/list.rb', line 101 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.
345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/dry/monads/list.rb', line 345 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
370 371 372 |
# File 'lib/dry/monads/list.rb', line 370 def deconstruct value end |
#empty? ⇒ TrueClass, FalseClass
Whether the list is empty.
203 204 205 |
# File 'lib/dry/monads/list.rb', line 203 def empty? value.empty? end |
#filter(&block) ⇒ List Also known as: select
Filters elements with a block
217 218 219 |
# File 'lib/dry/monads/list.rb', line 217 def filter(&block) coerce(value.select(&block)) end |
#first ⇒ Object
Returns the first element.
170 171 172 |
# File 'lib/dry/monads/list.rb', line 170 def first value.first end |
#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.
119 120 121 122 123 124 125 126 |
# File 'lib/dry/monads/list.rb', line 119 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, &block) ⇒ Object Also known as: foldl, reduce
Folds the list from the left.
185 186 187 |
# File 'lib/dry/monads/list.rb', line 185 def fold_left(initial, &block) value.reduce(initial, &block) end |
#fold_right(initial) ⇒ Object Also known as: foldr
Folds the list from the right.
195 196 197 |
# File 'lib/dry/monads/list.rb', line 195 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`.
239 240 241 |
# File 'lib/dry/monads/list.rb', line 239 def head Monads::Maybe.coerce(value.first) end |
#inspect ⇒ String Also known as: to_s
Returns a string representation of the list.
157 158 159 160 |
# File 'lib/dry/monads/list.rb', line 157 def inspect type_ann = typed? ? "<#{type.name.split("::").last}>" : "" "List#{type_ann}#{value.inspect}" end |
#last ⇒ Object
Returns the last element.
177 178 179 |
# File 'lib/dry/monads/list.rb', line 177 def last value.last end |
#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
132 133 134 135 136 137 138 |
# File 'lib/dry/monads/list.rb', line 132 def map(&block) if block_given? fmap(block) else value.map end end |
#monad ⇒ Monad
Returns the List monad.
316 317 318 |
# File 'lib/dry/monads/list.rb', line 316 def monad List end |
#reverse ⇒ List
Reverses the list.
232 233 234 |
# File 'lib/dry/monads/list.rb', line 232 def reverse coerce(value.reverse) end |
#size ⇒ Integer
List size.
225 226 227 |
# File 'lib/dry/monads/list.rb', line 225 def size value.size end |
#sort ⇒ List
Sorts the list.
210 211 212 |
# File 'lib/dry/monads/list.rb', line 210 def sort coerce(value.sort) end |
#tail ⇒ List
Returns list’s tail.
246 247 248 |
# File 'lib/dry/monads/list.rb', line 246 def tail coerce(value.drop(1)) end |
#to_monad ⇒ List
Returns self.
323 324 325 |
# File 'lib/dry/monads/list.rb', line 323 def to_monad self end |
#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.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/dry/monads/list.rb', line 289 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.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/dry/monads/list.rb', line 255 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
275 276 277 |
# File 'lib/dry/monads/list.rb', line 275 def typed? !type.nil? end |