Skip to content

Commit ac47b33

Browse files
committed
+ (Value)Task.mapError
1 parent 86cb448 commit ac47b33

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

src/FSharpPlus/Extensions/Task.fs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,27 @@ module Task =
376376
let source = nullArgCheck (nameof source) source
377377

378378
tryWith (fun () -> source) (mapper >> Task.FromResult)
379+
380+
/// <summary>Maps the exception of a faulted task to another exception.</summary>
381+
/// <param name="mapping">Mapping function from exception to exception.</param>
382+
/// <param name="source">The source task.</param>
383+
/// <returns>The resulting task.</returns>
384+
let mapError (mapping: exn -> exn) (source: Task<'T>) : Task<'T> =
385+
let source = nullArgCheck (nameof source) source
386+
387+
if source.IsCompleted then
388+
match source with
389+
| Succeeded _ -> source
390+
| Faulted exn -> FromExceptions (AggregateException (mapping exn))
391+
| Canceled -> source
392+
else
393+
let tcs = TaskCompletionSource<'T> TaskCreationOptions.RunContinuationsAsynchronously
394+
let k = function
395+
| Succeeded r -> tcs.SetResult r
396+
| Faulted aex -> tcs.SetException (AggregateException (mapping aex)).InnerExceptions
397+
| Canceled -> tcs.SetCanceled ()
398+
source.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> k source)
399+
tcs.Task
379400

380401
/// <summary>Creates a Task that's completed unsuccessfully with the specified exception.</summary>
381402
/// <param name="exn">The exception to be raised.</param>

src/FSharpPlus/Extensions/ValueTask.fs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,25 @@ module ValueTask =
346346
let inline recover ([<InlineIfLambda>]mapper: exn -> 'T) (source: ValueTask<'T>) : ValueTask<'T> =
347347
tryWith (mapper >> ValueTask.FromResult) (fun () -> source)
348348

349+
/// <summary>Maps the exception of a faulted task to another exception.</summary>
350+
/// <param name="mapping">Mapping function from exception to exception.</param>
351+
/// <param name="source">The source task.</param>
352+
/// <returns>The resulting task.</returns>
353+
let mapError (mapping: exn -> exn) (source: ValueTask<'T>) : ValueTask<'T> =
354+
if source.IsCompleted then
355+
match source with
356+
| Succeeded _ -> source
357+
| Faulted exn -> FromExceptions (AggregateException (mapping exn))
358+
| Canceled -> source
359+
else
360+
let tcs = TaskCompletionSource<'T> TaskCreationOptions.RunContinuationsAsynchronously
361+
let k = function
362+
| Succeeded r -> tcs.SetResult r
363+
| Faulted aex -> tcs.SetException (AggregateException (mapping aex)).InnerExceptions
364+
| Canceled -> tcs.SetCanceled ()
365+
source.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> k source)
366+
ValueTask<'T> tcs.Task
367+
349368
/// <summary>Creates a ValueTask that's completed unsuccessfully with the specified exception.</summary>
350369
/// <param name="exn">The exception to be raised.</param>
351370
/// <returns>A ValueTask that is completed unsuccessfully with the specified exception.</returns>

0 commit comments

Comments
 (0)