diff --git a/src/FSharpPlus/Extensions/Async.fs b/src/FSharpPlus/Extensions/Async.fs
index 09fc152ed..71f918b45 100644
--- a/src/FSharpPlus/Extensions/Async.fs
+++ b/src/FSharpPlus/Extensions/Async.fs
@@ -10,7 +10,7 @@ module Async =
let map f x = async.Bind (x, async.Return << f)
/// Creates an async workflow from two workflows 'x' and 'y', mapping its results with 'f'.
- /// Workflows are run in sequence.
+ /// Workflows are run in sequence, for parallel use pmap2.
/// The mapping function.
/// First async workflow.
/// Second async workflow.
@@ -20,7 +20,7 @@ module Async =
return f a b}
/// Creates an async workflow from three workflows 'x', 'y' and 'z', mapping its results with 'f'.
- /// Workflows are run in sequence.
+ /// Workflows are run in sequence, for parallel use pmap3.
/// The mapping function.
/// First async workflow.
/// Second async workflow.
@@ -31,6 +31,43 @@ module Async =
let! c = z
return f a b c}
+ /// Creates an async workflow from two workflows 'x' and 'y', mapping its results with 'f'.
+ /// Similar to map2 but workflows are run in parallel.
+ /// The mapping function.
+ /// First async workflow.
+ /// Second async workflow.
+ #if FABLE_COMPILER
+ let pmap2 f x y = map2 f x y
+ #else
+ let pmap2 f x y = async {
+ let! ct = Async.CancellationToken
+ let x = Async.StartImmediateAsTask (x, ct)
+ let y = Async.StartImmediateAsTask (y, ct)
+ let! x' = Async.AwaitTask x
+ let! y' = Async.AwaitTask y
+ return f x' y' }
+ #endif
+
+ /// Creates an async workflow from three workflows 'x', 'y' and 'z', mapping its results with 'f'.
+ /// Similar to map3 but workflows are run in parallel.
+ /// The mapping function.
+ /// First async workflow.
+ /// Second async workflow.
+ /// third async workflow.
+ #if FABLE_COMPILER
+ let pmap3 f x y z = map3 f x y z
+ #else
+ let pmap3 f x y z = async {
+ let! ct = Async.CancellationToken
+ let x = Async.StartImmediateAsTask (x, ct)
+ let y = Async.StartImmediateAsTask (y, ct)
+ let z = Async.StartImmediateAsTask (z, ct)
+ let! x' = Async.AwaitTask x
+ let! y' = Async.AwaitTask y
+ let! z' = Async.AwaitTask z
+ return f x' y' z' }
+ #endif
+
/// Creates an async workflow from two workflows 'x' and 'y', tupling its results.
let zip x y = async {
let! a = x
diff --git a/src/FSharpPlus/Extensions/Task.fs b/src/FSharpPlus/Extensions/Task.fs
index b10569567..1b87d8653 100644
--- a/src/FSharpPlus/Extensions/Task.fs
+++ b/src/FSharpPlus/Extensions/Task.fs
@@ -134,6 +134,28 @@ module Task =
) |> ignore) |> ignore) |> ignore
tcs.Task
+ /// Creates a task workflow from two workflows 'x' and 'y', mapping its results with 'f'.
+ /// Similar to map2 but workflows are run in parallel.
+ /// The mapping function.
+ /// First task workflow.
+ /// Second task workflow.
+ let pmap2 f x y = task {
+ let! x' = x
+ let! y' = y
+ return f x' y' }
+
+ /// Creates a task workflow from three workflows 'x', 'y' and z, mapping its results with 'f'.
+ /// Similar to map2 but workflows are run in parallel.
+ /// The mapping function.
+ /// First task workflow.
+ /// Second task workflow.
+ /// Third task workflow.
+ let pmap3 f x y z = task {
+ let! x' = x
+ let! y' = y
+ let! z' = z
+ return f x' y' z' }
+
/// Creates a task workflow that is the result of applying the resulting function of a task workflow
/// to the resulting value of another task workflow
/// Task workflow returning a function
diff --git a/src/FSharpPlus/Extensions/ValueTask.fs b/src/FSharpPlus/Extensions/ValueTask.fs
index 1138bcf5b..669470975 100644
--- a/src/FSharpPlus/Extensions/ValueTask.fs
+++ b/src/FSharpPlus/Extensions/ValueTask.fs
@@ -62,6 +62,35 @@ module ValueTask =
with e -> tcs.SetException e)))
tcs.Task |> ValueTask<'W>
+ /// Creates a task workflow from two workflows 'x' and 'y', mapping its results with 'f'.
+ /// Similar to map2 but workflows are run in parallel.
+ /// The mapping function.
+ /// First ValueTask workflow.
+ /// Second ValueTask workflow.
+ /// Third ValueTask workflow.
+ let pmap2 (f: 'T -> 'U -> 'V) (x: ValueTask<'T>) (y: ValueTask<'U>) : ValueTask<'V> =
+ task {
+ let! x' = x
+ let! y' = y
+ return f x' y'
+ }
+ |> ValueTask<'V>
+
+ /// Creates a ValueTask workflow from three workflows 'x', 'y' and z, mapping its results with 'f'.
+ /// Similar to map3 but workflows are run in parallel.
+ /// The mapping function.
+ /// First ValueTask workflow.
+ /// Second ValueTask workflow.
+ /// Third ValueTask workflow.
+ let pmap3 (f: 'T -> 'U -> 'V -> 'W) (x: ValueTask<'T>) (y: ValueTask<'U>) (z: ValueTask<'V>) : ValueTask<'W> =
+ task {
+ let! x' = x
+ let! y' = y
+ let! z' = z
+ return f x' y' z'
+ }
+ |> ValueTask<'W>
+
/// Creates a ValueTask workflow that is the result of applying the resulting function of a ValueTask workflow
/// to the resulting value of another ValueTask workflow
/// ValueTask workflow returning a function