From 5bbec2f286b0974d8217cc3ec9f7180498b79d00 Mon Sep 17 00:00:00 2001 From: Oskar Gewalli Date: Mon, 8 Jan 2024 19:39:26 +0200 Subject: [PATCH 1/3] Publish to GitHub package feed --- .github/workflows/dotnetcore.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 3890b2152..e893afe32 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -5,10 +5,6 @@ env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true # Disable sending usage data to Microsoft DOTNET_CLI_TELEMETRY_OPTOUT: true - # GitHub Packages Feed settings - GITHUB_FEED: https://nuget.pkg.github.com/fsprojects - GITHUB_USER: fsprojects - #GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} on: push: @@ -41,7 +37,9 @@ jobs: package: runs-on: windows-latest - + permissions: + packages: write + contents: read steps: - uses: actions/checkout@v2 - name: Setup .NET Core @@ -74,13 +72,14 @@ jobs: with: name: nupkg path: ./bin/nupkg/*.nupkg - #- name: Push to GitHub Feed - # shell: bash - # run: | - # for f in ./bin/nupkg/*.nupkg - # do - # curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED - # done + - name: Push to GitHub Feed + shell: bash + run: | + for f in ./bin/nupkg/*.nupkg + do + echo $f + dotnet nuget push $f -k ${{ secrets.GITHUB_TOKEN }} -s https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json + done docs: runs-on: windows-latest From 3e7a328db725ae2958d4df050f37df315deaa311 Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Sat, 13 Jan 2024 07:29:13 +0100 Subject: [PATCH 2/3] + map3Shortest and zip3shortest to Array and ResizeArray --- src/FSharpPlus/Extensions/Array.fs | 22 ++++++++++++++++++++++ src/FSharpPlus/Extensions/ResizeArray.fs | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/FSharpPlus/Extensions/Array.fs b/src/FSharpPlus/Extensions/Array.fs index 26a13ab0a..5113cbd70 100644 --- a/src/FSharpPlus/Extensions/Array.fs +++ b/src/FSharpPlus/Extensions/Array.fs @@ -238,6 +238,15 @@ module Array = Array.init (min a1.Length a2.Length) (fun i -> f a1.[i] a2.[i]) + /// Safely build a new array whose elements are the results of applying the given function + /// to each of the elements of the three arrays pairwise. + /// If one array is shorter, excess elements are discarded from the right end of the longer array. + let map3Shortest f (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) = + raiseIfNull (nameof a1) a1 + raiseIfNull (nameof a2) a2 + raiseIfNull (nameof a3) a3 + Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> f a1.[i] a2.[i] a3.[i]) + /// /// Zip safely two arrays. If one array is shorter, excess elements are discarded from the right end of the longer array. /// @@ -250,6 +259,19 @@ module Array = Array.init (min a1.Length a2.Length) (fun i -> a1.[i], a2.[i]) + /// + /// Zip safely three arrays. If one array is shorter, excess elements are discarded from the right end of the longer array. + /// + /// First input array. + /// Second input array. + /// Third input array. + /// Array with corresponding tuple of input arrays. + let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) = + raiseIfNull (nameof a1) a1 + raiseIfNull (nameof a2) a2 + raiseIfNull (nameof a3) a3 + Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> a1.[i], a2.[i], a3.[i]) + /// Same as choose but with access to the index. /// The mapping function, taking index and element as parameters. /// The input array. diff --git a/src/FSharpPlus/Extensions/ResizeArray.fs b/src/FSharpPlus/Extensions/ResizeArray.fs index 330b9b630..72de31931 100644 --- a/src/FSharpPlus/Extensions/ResizeArray.fs +++ b/src/FSharpPlus/Extensions/ResizeArray.fs @@ -134,6 +134,16 @@ module ResizeArray = ra.Add (f a1.[i] a2.[i]) ra + /// Safely build a new ResizeArray whose elements are the results of applying the given function + /// to each of the elements of the three ResizeArrays pairwise. + /// If one array is shorter, excess elements are discarded from the right end of the longer array. + let map3Shortest f (a1: ResizeArray<'T1>) (a2: ResizeArray<'T2>) (a3: ResizeArray<'T3>) = + let len = min a1.Count a2.Count |> min a3.Count + let ra = ResizeArray len + for i in 0..(len-1) do + ra.Add (f a1.[i] a2.[i] a3.[i]) + ra + /// /// Zip safely two ResizeArrays. If one ResizeArray is shorter, excess elements are discarded from the right end of the longer ResizeArray. /// @@ -146,3 +156,17 @@ module ResizeArray = for i in 0..(len-1) do ra.Add (a1.[i], a2.[i]) ra + + /// + /// Zip safely three ResizeArrays. If one ResizeArray is shorter, excess elements are discarded from the right end of the longer ResizeArray. + /// + /// First input ResizeArray. + /// Second input ResizeArray. + /// Third input ResizeArray. + /// ResizeArray with corresponding pairs of input ResizeArrays. + let zip3Shortest (a1: ResizeArray<'T1>) (a2: ResizeArray<'T2>) (a3: ResizeArray<'T3>) = + let len = min a1.Count a2.Count |> min a3.Count + let ra = ResizeArray len + for i in 0..(len-1) do + ra.Add (a1.[i], a2.[i], a3.[i]) + ra From 2e2f4326b849ec79be4df22db4e6f6096cc7a98b Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Sat, 13 Jan 2024 07:35:34 +0100 Subject: [PATCH 3/3] + pmap2 and pmap3 to Async, Task and ValueTask --- src/FSharpPlus/Extensions/Async.fs | 37 ++++++++++++++++++++++++++ src/FSharpPlus/Extensions/Task.fs | 22 +++++++++++++++ src/FSharpPlus/Extensions/ValueTask.fs | 29 ++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/src/FSharpPlus/Extensions/Async.fs b/src/FSharpPlus/Extensions/Async.fs index 09fc152ed..4d2ffae3d 100644 --- a/src/FSharpPlus/Extensions/Async.fs +++ b/src/FSharpPlus/Extensions/Async.fs @@ -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