Class: Dry::Monads::Task
- Inherits:
-
Object
- Object
- Dry::Monads::Task
- Defined in:
- lib/dry/monads/task.rb,
lib/dry/monads/maybe.rb,
lib/dry/monads/result.rb
Overview
The Task monad represents an async computation. The implementation is a rather thin wrapper of Concurrent::Promise from the concurrent-ruby. The API supports setting a custom executor from concurrent-ruby.
Direct Known Subclasses
Defined Under Namespace
Modules: Mixin
Class Method Summary collapse
-
.[](executor, &block) ⇒ Task
Creates a Task with the given executor.
-
.failed(exc) ⇒ Task
Returns a failed task from the given exception.
-
.new(promise = nil, &block) ⇒ Object
Creates a Task from a block.
-
.pure(value = Undefined, &block) ⇒ Object
Returns a completed task from the given value.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compares two tasks.
-
#apply(val = Undefined, &block) ⇒ Task
Applies the stored value to the given argument.
-
#bind(&block) ⇒ Task
Composes two tasks to run one after another.
-
#complete? ⇒ Boolean
Whether the computation is complete.
-
#discard ⇒ Task
Maps a successful result to Unit, effectively discards it.
-
#fmap(&block) ⇒ Task
Lifts a block over the Task monad.
-
#initialize(promise) ⇒ Task
constructor
private
A new instance of Task.
- #monad ⇒ Class
-
#or(&block) ⇒ Object
Rescues the error with a block that returns another task.
-
#or_fmap(&block) ⇒ Task
Tranforms the error if the computation wasn’t successful.
-
#to_maybe ⇒ Maybe
Converts to Maybe.
-
#to_monad ⇒ Maybe::Some, Maybe::None
Returns self.
-
#to_result ⇒ Result
Converts to Result.
- #to_s ⇒ String (also: #inspect)
-
#value! ⇒ Object
Retrieves the value of the computation.
-
#value_or(&block) ⇒ Object
Extracts the resulting value if the computation was successful otherwise yields the block and returns its result.
-
#wait(timeout = nil) ⇒ Task
Blocks the current thread until the task is complete.
Constructor Details
#initialize(promise) ⇒ Task
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 Task.
89 90 91 |
# File 'lib/dry/monads/task.rb', line 89 def initialize(promise) @promise = promise end |
Class Method Details
.[](executor, &block) ⇒ Task
Creates a Task with the given executor
53 54 55 |
# File 'lib/dry/monads/task.rb', line 53 def [](executor, &block) new(Promise.execute(executor: executor, &block)) end |
.failed(exc) ⇒ Task
Returns a failed task from the given exception
76 77 78 |
# File 'lib/dry/monads/task.rb', line 76 def failed(exc) new(Promise.reject(exc)) end |
Instance Method Details
#==(other) ⇒ Boolean
Compares two tasks. Note, it works good enough only for complete tasks.
199 200 201 202 203 204 |
# File 'lib/dry/monads/task.rb', line 199 def ==(other) return true if equal?(other) return false unless self.class == other.class compare_promises(promise, other.promise) end |
#apply(val = Undefined, &block) ⇒ Task
Applies the stored value to the given argument.
236 237 238 239 |
# File 'lib/dry/monads/task.rb', line 236 def apply(val = Undefined, &block) arg = Undefined.default(val, &block) bind { |f| arg.fmap { curry(f).(_1) } } end |
#bind(&block) ⇒ Task
Composes two tasks to run one after another. A more common name is ‘then` exists as an alias.
123 124 125 |
# File 'lib/dry/monads/task.rb', line 123 def bind(&block) self.class.new(promise.flat_map { block.(_1).promise }) end |
#complete? ⇒ Boolean
Whether the computation is complete.
209 210 211 |
# File 'lib/dry/monads/task.rb', line 209 def complete? promise.complete? end |
#discard ⇒ Task
Maps a successful result to Unit, effectively discards it
244 245 246 |
# File 'lib/dry/monads/task.rb', line 244 def discard fmap { Unit } end |
#fmap(&block) ⇒ Task
Lifts a block over the Task monad.
113 114 115 |
# File 'lib/dry/monads/task.rb', line 113 def fmap(&block) self.class.new(promise.then(&block)) end |
#or(&block) ⇒ Object
Rescues the error with a block that returns another task.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/dry/monads/task.rb', line 159 def or(&block) child = Promise.new( parent: promise, executor: Concurrent::ImmediateExecutor.new ) promise.on_error do |v| inner = block.(v).promise inner.execute inner.on_success { child.on_fulfill(_1) } inner.on_error { child.on_reject(_1) } rescue StandardError => e child.on_reject(e) end promise.on_success { child.on_fulfill(_1) } self.class.new(child) end |
#or_fmap(&block) ⇒ Task
Tranforms the error if the computation wasn’t successful.
151 152 153 |
# File 'lib/dry/monads/task.rb', line 151 def or_fmap(&block) self.class.new(promise.rescue(&block)) end |
#to_maybe ⇒ Maybe
Converts to Maybe. Blocks the current thread if required.
406 407 408 409 410 411 412 |
# File 'lib/dry/monads/maybe.rb', line 406 def to_maybe if promise.wait.fulfilled? Maybe::Some.new(promise.value) else Maybe::None.new(RightBiased::Left.trace_caller) end end |
#to_monad ⇒ Maybe::Some, Maybe::None
Returns self.
221 222 223 |
# File 'lib/dry/monads/task.rb', line 221 def to_monad self end |
#to_result ⇒ Result
Converts to Result. Blocks the current thread if required.
433 434 435 436 437 438 439 |
# File 'lib/dry/monads/result.rb', line 433 def to_result if promise.wait.fulfilled? Result::Success.new(promise.value) else Result::Failure.new(promise.reason, RightBiased::Left.trace_caller) end end |
#to_s ⇒ String Also known as: inspect
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/dry/monads/task.rb', line 129 def to_s state = case promise.state when :fulfilled if Unit.equal?(value!) "value=()" else "value=#{value!.inspect}" end when :rejected "error=#{promise.reason.inspect}" else "?" end "Task(#{state})" end |
#value! ⇒ Object
Retrieves the value of the computation. Blocks current thread if the underlying promise hasn’t been complete yet. Throws an error if the computation failed.
100 101 102 103 104 105 106 |
# File 'lib/dry/monads/task.rb', line 100 def value! if promise.wait.fulfilled? promise.value else raise promise.reason end end |
#value_or(&block) ⇒ Object
Extracts the resulting value if the computation was successful otherwise yields the block and returns its result.
183 184 185 |
# File 'lib/dry/monads/task.rb', line 183 def value_or(&block) promise.rescue(&block).wait.value end |
#wait(timeout = nil) ⇒ Task
Blocks the current thread until the task is complete.
190 191 192 193 |
# File 'lib/dry/monads/task.rb', line 190 def wait(timeout = nil) promise.wait(timeout) self end |