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) ⇒ Task
Creates a Task with the given executor.
-
.failed(exc) ⇒ Task
Returns a failed task from the given exception.
-
.new(promise = nil) ⇒ 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) ⇒ 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 ⇒ 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 ⇒ 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 ⇒ 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.
87 88 89 |
# File 'lib/dry/monads/task.rb', line 87 def initialize(promise) @promise = promise end |
Class Method Details
.[](executor) ⇒ Task
Creates a Task with the given executor
53 54 55 |
# File 'lib/dry/monads/task.rb', line 53 def [](executor, &) new(Promise.execute(executor: executor, &)) end |
.failed(exc) ⇒ Task
Returns a failed task from the given exception
76 |
# File 'lib/dry/monads/task.rb', line 76 def failed(exc) = new(Promise.reject(exc)) |
Instance Method Details
#==(other) ⇒ Boolean
Compares two tasks. Note, it works good enough only for complete tasks.
191 192 193 194 195 196 |
# File 'lib/dry/monads/task.rb', line 191 def ==(other) return true if equal?(other) return false unless self.class == other.class compare_promises(promise, other.promise) end |
#apply(val = Undefined) ⇒ Task
Applies the stored value to the given argument.
222 223 224 225 |
# File 'lib/dry/monads/task.rb', line 222 def apply(val = Undefined, &) arg = Undefined.default(val, &) 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.
119 120 121 |
# File 'lib/dry/monads/task.rb', line 119 def bind(&block) self.class.new(promise.flat_map { block.(_1).promise }) end |
#complete? ⇒ Boolean
Whether the computation is complete.
201 |
# File 'lib/dry/monads/task.rb', line 201 def complete? = promise.complete? |
#discard ⇒ Task
Maps a successful result to Unit, effectively discards it
230 |
# File 'lib/dry/monads/task.rb', line 230 def discard = fmap { Unit } |
#fmap ⇒ Task
Lifts a block over the Task monad.
111 |
# File 'lib/dry/monads/task.rb', line 111 def fmap(&) = self.class.new(promise.then(&)) |
#or(&block) ⇒ Object
Rescues the error with a block that returns another task.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/dry/monads/task.rb', line 153 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 ⇒ Task
Tranforms the error if the computation wasn’t successful.
147 |
# File 'lib/dry/monads/task.rb', line 147 def or_fmap(&) = self.class.new(promise.rescue(&)) |
#to_maybe ⇒ Maybe
Converts to Maybe. Blocks the current thread if required.
375 376 377 378 379 380 381 |
# File 'lib/dry/monads/maybe.rb', line 375 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.
209 |
# File 'lib/dry/monads/task.rb', line 209 def to_monad = self |
#to_result ⇒ Result
Converts to Result. Blocks the current thread if required.
397 398 399 400 401 402 403 |
# File 'lib/dry/monads/result.rb', line 397 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
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/dry/monads/task.rb', line 125 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.
98 99 100 101 102 103 104 |
# File 'lib/dry/monads/task.rb', line 98 def value! if promise.wait.fulfilled? promise.value else raise promise.reason end end |
#value_or ⇒ Object
Extracts the resulting value if the computation was successful otherwise yields the block and returns its result.
177 |
# File 'lib/dry/monads/task.rb', line 177 def value_or(&) = promise.rescue(&).wait.value |
#wait(timeout = nil) ⇒ Task
Blocks the current thread until the task is complete.
182 183 184 185 |
# File 'lib/dry/monads/task.rb', line 182 def wait(timeout = nil) promise.wait(timeout) self end |