@@ -355,6 +355,20 @@ Converts a `EAsync` to a `ExceptTask`.
355355protected def toEIO (x : EAsync ε α) : EIO ε (ExceptTask ε α) :=
356356 MaybeExceptTask.toTask <$> x.toRawEIO
357357
358+ /--
359+ Creates a new `EAsync` out of a `Task`.
360+ -/
361+ @[inline]
362+ protected def ofTask (x : Task α) : EAsync ε α :=
363+ .mk (pure (MaybeExceptTask.ofTask <| x.map (.ok)))
364+
365+ /--
366+ Creates a new `EAsync` out of a `ExceptTask`.
367+ -/
368+ @[inline]
369+ protected def ofExceptTask (x : ExceptTask ε α) : EAsync ε α :=
370+ .mk (pure (MaybeExceptTask.ofTask x))
371+
358372/--
359373Creates an `EAsync` computation that immediately returns the given value.
360374-/
@@ -475,6 +489,9 @@ def async (self : EAsync ε α) : EAsync ε (ExceptTask ε α) :=
475489instance : MonadAwait (ExceptTask ε) (EAsync ε) where
476490 await t := mk <| pure <| .ofTask t
477491
492+ instance : MonadAwait Task (EAsync ε) where
493+ await t := mk <| pure <| .ofTask (t.map (.ok))
494+
478495instance : MonadAwait AsyncTask (EAsync IO.Error) where
479496 await t := mk <| pure <| .ofTask t
480497
@@ -515,13 +532,6 @@ instance : OrElse (EAsync ε α) where
515532instance [Inhabited ε] : Inhabited (EAsync ε α) where
516533 default := ⟨.error default⟩
517534
518- /--
519- Starts the given `ExceptTask` in the background and discards the result.
520- -/
521- @[inline]
522- def parallel {α : Type } (x : EAsync ε (ExceptTask ε α)) : EAsync ε Unit :=
523- discard <| x
524-
525535/--
526536A tail recursive version of the `forIn` for while loops inside the `EAsync` Monad.
527537-/
@@ -579,9 +589,16 @@ Returns the `Async` computation inside an `AsyncTask`, so it can be awaited.
579589def async (self : Async α) : Async (AsyncTask α) :=
580590 EAsync.lift <| self.asTask
581591
582- @[default_instance] instance : MonadAwait AsyncTask Async := inferInstanceAs (MonadAwait AsyncTask (EAsync IO.Error))
583- @[default_instance] instance : MonadAsync AsyncTask Async := inferInstanceAs (MonadAsync (ExceptTask IO.Error) (EAsync IO.Error))
584- instance : MonadAwait IO.Promise Async := inferInstanceAs (MonadAwait IO.Promise (EAsync IO.Error))
592+ @[default_instance]
593+ instance : MonadAwait AsyncTask Async :=
594+ inferInstanceAs (MonadAwait AsyncTask (EAsync IO.Error))
595+
596+ @[default_instance]
597+ instance : MonadAsync AsyncTask Async :=
598+ inferInstanceAs (MonadAsync (ExceptTask IO.Error) (EAsync IO.Error))
599+
600+ instance : MonadAwait IO.Promise Async :=
601+ inferInstanceAs (MonadAwait IO.Promise (EAsync IO.Error))
585602
586603end Async
587604
@@ -641,11 +658,74 @@ instance : MonadAwait Task BaseAsync where
641658instance : MonadAsync Task BaseAsync where
642659 async := BaseAsync.async
643660
661+ instance : MonadLiftT BaseAsync (EAsync ε) where
662+ monadLift {α} x :=
663+ let r : EIO ε (MaybeExceptTask ε α) := do
664+ let r ← BaseIO.toEIO (x.toRawEIO)
665+ match r with
666+ | .pure res => pure <| .pure res
667+ | .ofTask t => pure <| .ofTask <| Task.map (fun (.ok t) => .ok t) t
668+ ⟨r⟩
669+
670+ instance : MonadLiftT BaseAsync Async :=
671+ inferInstanceAs (MonadLiftT BaseAsync (EAsync IO.Error))
672+
644673end BaseAsync
645674
646675export MonadAsync (async)
647676export MonadAwait (await)
648- export EAsync (parallel)
677+
678+ /--
679+ Starts the given async task in the background and discards the result.
680+ -/
681+ @[inline, specialize]
682+ def parallel [Monad m] [MonadAsync t m] (x : m (t α)) : m Unit :=
683+ discard <| x
684+
685+ /--
686+ Runs two computations concurrently and returns both results as a pair.
687+ -/
688+ @[inline, specialize]
689+ def concurrently [Monad m] [MonadAwait t m] [MonadAsync t m] (x : m α) (y : m β) : m (α × β) := do
690+ let taskX : t α ← async x
691+ let taskY : t β ← async y
692+ let resultX ← await taskX
693+ let resultY ← await taskY
694+ return (resultX, resultY)
695+
696+ /--
697+ Runs two computations concurrently and returns the result of the one that finishes first.
698+ The other result is discarded.
699+ -/
700+ @[inline, specialize]
701+ def race [MonadLiftT BaseIO m] [MonadAwait Task m] [MonadAsync t m] [MonadAwait t m] [Monad m] [Inhabited α] (x : m α) (y : m α) : m α := do
702+ let promise ← IO.Promise.new
703+
704+ discard (async (n := t) <| Bind.bind x (liftM ∘ promise.resolve))
705+ discard (async (n := t) <| Bind.bind y (liftM ∘ promise.resolve))
706+
707+ await promise.result!
708+
709+ /--
710+ Runs all computations in an `Array` concurrently and returns all results as an array.
711+ -/
712+ @[inline, specialize]
713+ def concurrentlyAll [Monad m] [MonadAwait t m] [MonadAsync t m] (xs : Array (m α)) : m (Array α) := do
714+ let tasks : Array (t α) ← xs.mapM async
715+ tasks.mapM await
716+
717+ /--
718+ Runs all computations concurrently and returns the result of the first one to finish.
719+ All other results are discarded.
720+ -/
721+ @[inline, specialize]
722+ def raceAll [ForM m c (m α)] [MonadLiftT BaseIO m] [MonadAwait Task m] [MonadAsync t m] [MonadAwait t m] [Monad m] [Inhabited α] (xs : c) : m α := do
723+ let promise ← IO.Promise.new
724+
725+ ForM.forM xs fun x =>
726+ discard (async (n := t) <| Bind.bind x (liftM ∘ promise.resolve))
727+
728+ await promise.result!
649729
650730end Async
651731end IO
0 commit comments