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.
-
.new(promise = nil, &block) ⇒ Object
Creates a Task from a block.
-
.pure(value = Undefined, &block) ⇒ Object
Returns a complete 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
(also: #then)
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.
80 81 82 |
# File 'lib/dry/monads/task.rb', line 80 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 |
Instance Method Details
#==(other) ⇒ Boolean
Compares two tasks. Note, it works good enough only for complete tasks.
188 189 190 191 192 |
# File 'lib/dry/monads/task.rb', line 188 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.
224 225 226 227 |
# File 'lib/dry/monads/task.rb', line 224 def apply(val = Undefined) arg = Undefined.default(val) { yield } bind { |f| arg.fmap { |v| curry(f).(v) } } end |
#bind(&block) ⇒ Task Also known as: then
Composes two tasks to run one after another.
A more common name is then
exists as an alias.
114 115 116 |
# File 'lib/dry/monads/task.rb', line 114 def bind(&block) self.class.new(promise.flat_map { |value| block.(value).promise }) end |
#complete? ⇒ Boolean
Whether the computation is complete.
197 198 199 |
# File 'lib/dry/monads/task.rb', line 197 def complete? promise.complete? end |
#discard ⇒ Task
Maps a successful result to Unit, effectively discards it
232 233 234 |
# File 'lib/dry/monads/task.rb', line 232 def discard fmap { Unit } end |
#fmap(&block) ⇒ Task
Lifts a block over the Task monad.
104 105 106 |
# File 'lib/dry/monads/task.rb', line 104 def fmap(&block) self.class.new(promise.then(&block)) end |
#or(&block) ⇒ Object
Rescues the error with a block that returns another task.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/dry/monads/task.rb', line 146 def or(&block) child = Promise.new( parent: promise, executor: Concurrent::ImmediateExecutor.new ) promise.on_error do |v| begin inner = block.(v).promise inner.execute inner.on_success { |r| child.on_fulfill(r) } inner.on_error { |e| child.on_reject(e) } rescue => e child.on_reject(e) end end promise.on_success { |v| child.on_fulfill(v) } self.class.new(child) end |
#or_fmap(&block) ⇒ Task
Tranforms the error if the computation wasn't successful.
138 139 140 |
# File 'lib/dry/monads/task.rb', line 138 def or_fmap(&block) self.class.new(promise.rescue(&block)) end |
#to_maybe ⇒ Maybe
Converts to Maybe. Blocks the current thread if required.
255 256 257 258 259 260 261 |
# File 'lib/dry/monads/maybe.rb', line 255 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 210 211 |
# File 'lib/dry/monads/task.rb', line 209 def to_monad self end |
#to_result ⇒ Result
Converts to Result. Blocks the current thread if required.
324 325 326 327 328 329 330 |
# File 'lib/dry/monads/result.rb', line 324 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
120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/dry/monads/task.rb', line 120 def to_s state = case promise.state when :fulfilled "value=#{ value!.inspect }" 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.
91 92 93 94 95 96 97 |
# File 'lib/dry/monads/task.rb', line 91 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.
172 173 174 |
# File 'lib/dry/monads/task.rb', line 172 def value_or(&block) promise.rescue(&block).wait.value end |
#wait(timeout = nil) ⇒ Task
Blocks the current thread until the task is complete.
179 180 181 182 |
# File 'lib/dry/monads/task.rb', line 179 def wait(timeout = nil) promise.wait(timeout) self end |