Task
The Task monad is a parallelized Try. Its goal is to combine the power of Crystal's fibers with monads: the work runs on a spawned fiber, and you collect the result when you need it.
Creating a Task
Pass a proc to new. The proc starts running on a new fiber immediately:
crystal
task = Monads::Task(Float64).new(->{ 10.0 / 2 })Collecting the result
receive blocks until the fiber finishes and returns a Try. The result is memoized, so calling receive again returns the same value without re-running the work:
crystal
task = Monads::Task(Int32).new(->{ 21 * 2 })
task.receive # => Try wrapping 42Converting to Maybe or Either
Like Try, a Task is meant to be turned into a Maybe or an Either. These call receive for you:
crystal
Monads::Task(Int32).new(->{ 21 * 2 }).to_maybe # => Just(42)
Monads::Task(Int32).new(->{ 21 * 2 }).to_either # => Right(Exception, Int32) 42
Monads::Task(Int32).new(->{ raise "boom" }).to_maybe # => Nothing(Int32)
Monads::Task(Int32).new(->{ raise "boom" }).to_either # => LeftException(Int32)When to use it
Reach for Task instead of Try when the work is independent and you want it to run concurrently with other fibers. Start several tasks, then receive (or convert) each one to gather the results:
crystal
a = Monads::Task(Int32).new(->{ slow_computation_one })
b = Monads::Task(Int32).new(->{ slow_computation_two })
# Both run concurrently; collect when ready
result_a = a.to_maybe
result_b = b.to_maybeSee the Task API reference for the full method list.