diff --git a/src/FSharp.Core/array.fs b/src/FSharp.Core/array.fs index 3d4ffa4474f..21fee099a9e 100644 --- a/src/FSharp.Core/array.fs +++ b/src/FSharp.Core/array.fs @@ -2081,7 +2081,7 @@ module Array = let private maxPartitions = Environment.ProcessorCount // The maximum number of partitions to use let private minChunkSize = 256 // The minimum size of a chunk to be sorted in parallel - let private createPartitionsUpTo maxIdxExclusive (array: 'T[]) = + let private createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize (array: 'T[]) = [| let chunkSize = match maxIdxExclusive with @@ -2098,6 +2098,98 @@ module Array = yield new ArraySegment<'T>(array, offset, maxIdxExclusive - offset) |] + let private createPartitionsUpTo maxIdxExclusive (array: 'T[]) = + createPartitionsUpToWithMinChunkSize maxIdxExclusive minChunkSize array + + (* This function is there also as a support vehicle for other aggregations. + It is public in order to be called from inlined functions, the benefit of inlining call into it is significant *) + [] + let reduceBy (projection: 'T -> 'U) (reduction: 'U -> 'U -> 'U) (array: 'T[]) = + checkNonNull "array" array + + if array.Length = 0 then + invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString + + let chunks = createPartitionsUpToWithMinChunkSize array.Length 2 array // We need at least 2 elements/chunk for 'reduction' + + let chunkResults = + Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked chunks.Length + + Parallel.For( + 0, + chunks.Length, + fun chunkIdx -> + let chunk = chunks[chunkIdx] + let mutable res = projection array[chunk.Offset] + let lastIdx = chunk.Offset + chunk.Count - 1 + + for i = chunk.Offset + 1 to lastIdx do + let projected = projection array[i] + res <- reduction res projected + + chunkResults[chunkIdx] <- res + ) + |> ignore + + let mutable finalResult = chunkResults[0] + + for i = 1 to chunkResults.Length - 1 do + finalResult <- reduction finalResult chunkResults[i] + + finalResult + + [] + let inline reduce ([] reduction) (array: _[]) = + array |> reduceBy id reduction + + let inline vFst struct (a, _) = + a + + let inline vSnd struct (_, b) = + b + + [] + let inline minBy ([] projection) (array: _[]) = + + array + |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a < vFst b then a else b) + |> vSnd + + [] + let inline min (array: _[]) = + array |> reduce (fun a b -> if a < b then a else b) + + [] + let inline sumBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + if array.Length = 0 then + LanguagePrimitives.GenericZero + else + array |> reduceBy projection Operators.Checked.(+) + + [] + let inline sum (array: ^T[]) : ^T = + array |> sumBy id + + [] + let inline maxBy projection (array: _[]) = + + array + |> reduceBy (fun x -> struct (projection x, x)) (fun a b -> if vFst a > vFst b then a else b) + |> vSnd + + [] + let inline max (array: _[]) = + array |> reduce (fun a b -> if a > b then a else b) + + [] + let inline averageBy ([] projection: 'T -> ^U) (array: 'T[]) : ^U = + let sum = array |> reduceBy projection Operators.Checked.(+) + LanguagePrimitives.DivideByInt sum (array.Length) + + [] + let inline average (array: 'T[]) = + array |> averageBy id + [] let zip (array1: _[]) (array2: _[]) = checkNonNull "array1" array1 diff --git a/src/FSharp.Core/array.fsi b/src/FSharp.Core/array.fsi index ec0d228a365..3cd6996b132 100644 --- a/src/FSharp.Core/array.fsi +++ b/src/FSharp.Core/array.fsi @@ -3252,6 +3252,301 @@ module Array = [] val tryPick: chooser: ('T -> 'U option) -> array: 'T[] -> 'U option + /// Applies a function to each element of the array in parallel, threading an accumulator argument + /// through the computation for each thread involved in the computation. After processing entire input, results from all threads are reduced together. + /// Raises ArgumentException if the array is empty. + /// The order of processing is not guaranteed. For that reason, the 'reduce' function argument should be commutative. + /// (That is, changing the order of execution must not affect the result) + /// Also, compared to the non-parallel version of Array.reduce, the 'reduce' function may be invoked more times due to the resulting reduction from participating threads. + /// + /// The function to reduce a pair of elements to a single element. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// Result of the reductions. + /// + /// + /// + /// let inputs = [| 1; 3; 4; 2 |] + /// + /// inputs |> Array.Parallel.reduce (fun a b -> a + b) + /// + /// Evaluates to 1 + 3 + 4 + 2. However, the system could have decided to compute (1+3) and (4+2) first, and then put them together. + /// + + [] + [] + val inline reduce: reduction: ('T -> 'T -> 'T) -> array: 'T[] -> 'T + + /// Applies a projection function to each element of the array in parallel, reducing elements in each thread with a dedicated 'reduction' function. + /// After processing entire input, results from all threads are reduced together. + /// Raises ArgumentException if the array is empty. + /// The order of processing is not guaranteed. For that reason, the 'reduction' function argument should be commutative. + /// (That is, changing the order of execution must not affect the result) + /// + /// The function to project from elements of the input array + /// The function to reduce a pair of projected elements to a single element. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The final result of the reductions. + /// + /// + /// + /// let inputs = [| "1"; "3"; "4"; "2" |] + /// + /// inputs |> Array.Parallel.reduceBy (fun x -> int x) (+) + /// + /// Evaluates to 1 + 3 + 4 + 2. However, the system could have decided to compute (1+3) and (4+2) first, and then put them together. + /// + + [] + [] + val reduceBy: projection: ('T -> 'U) -> reduction: ('U -> 'U -> 'U) -> array: 'T[] -> 'U + + /// Returns the greatest of all elements of the array, compared via Operators.max. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The maximum element. + /// + /// + /// + /// let inputs = [| 10; 12; 11 |] + /// + /// inputs |> Array.Parallel.max + /// + /// Evaluates to 12 + /// + /// + /// + /// + /// let inputs: int[]= [| |] + /// + /// inputs |> Array.Parallel.max + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline max: array: 'T[] -> 'T when 'T: comparison + + /// Returns the greatest of all elements of the array, compared via Operators.max on the function result. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The function to transform the elements into a type supporting comparison. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The maximum element. + /// + /// + /// + /// let inputs = [| "aaa"; "b"; "cccc" |] + /// + /// inputs |> Array.Parallel.maxBy (fun s -> s.Length) + /// + /// Evaluates to "cccc" + /// + /// + /// + /// + /// let inputs: string[]= [| |] + /// + /// inputs |> Array.Parallel.maxBy (fun s -> s.Length) + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline maxBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + + /// Returns the smallest of all elements of the array, compared via Operators.min. + /// + /// Throws ArgumentException for empty arrays + /// + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The minimum element. + /// + /// + /// + /// let inputs = [| 10; 12; 11 |] + /// + /// inputs |> Array.Parallel.min + /// + /// Evaluates to 10 + /// + /// + /// + /// + /// let inputs: int[]= [| |] + /// + /// inputs |> Array.Parallel.min + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline min: array: 'T[] -> 'T when 'T: comparison + + /// Returns the lowest of all elements of the array, compared via Operators.min on the function result. + /// + /// Throws ArgumentException for empty arrays. + /// + /// The function to transform the elements into a type supporting comparison. + /// The input array. + /// + /// Thrown when the input array is null. + /// Thrown when the input array is empty. + /// + /// The minimum element. + /// + /// + /// + /// let inputs = [| "aaa"; "b"; "cccc" |] + /// + /// inputs |> Array.Parallel.minBy (fun s -> s.Length) + /// + /// Evaluates to "b" + /// + /// + /// + /// + /// let inputs: string[]= [| |] + /// + /// inputs |> Array.Parallel.minBy (fun s -> s.Length) + /// + /// Throws System.ArgumentException. + /// + [] + [] + val inline minBy: projection: ('T -> 'U) -> array: 'T[] -> 'T when 'U: comparison + + /// Returns the sum of the elements in the array. + /// + /// The input array. + /// + /// The resulting sum. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// let input = [| 1; 5; 3; 2 |] + /// + /// input |> Array.Parallel.sum + /// + /// Evaluates to 11. + /// + [] + [] + val inline sum: array: ^T[] -> ^T when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member Zero: ^T) + + /// Returns the sum of the results generated by applying the function to each element of the array. + /// + /// The function to transform the array elements into the type to be summed. + /// The input array. + /// + /// The resulting sum. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// let input = [| "aa"; "bbb"; "cc" |] + /// + /// input |> Array.Parallel.sumBy (fun s -> s.Length) + /// + /// Evaluates to 7. + /// + [] + [] + val inline sumBy: + projection: ('T -> ^U) -> array: 'T[] -> ^U + when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member Zero: ^U) + + /// Returns the average of the elements in the array. + /// + /// The input array. + /// + /// Thrown when array is empty. + /// Thrown when the input array is null. + /// + /// The average of the elements in the array. + /// + /// + /// + /// [| 1.0; 2.0; 6.0 |] |> Array.Parallel.average + /// + /// Evaluates to 3.0 + /// + /// + /// + /// + /// [| |] |> Array.Parallel.average + /// + /// Throws ArgumentException + /// + [] + [] + val inline average: + array: ^T[] -> ^T + when ^T: (static member (+): ^T * ^T -> ^T) and ^T: (static member DivideByInt: ^T * int -> ^T) + + /// Returns the average of the elements generated by applying the function to each element of the array. + /// + /// The function to transform the array elements before averaging. + /// The input array. + /// + /// Thrown when array is empty. + /// + /// The computed average. + /// + /// Thrown when the input array is null. + /// + /// + /// + /// type Foo = { Bar: float } + /// + /// let input = [| {Bar = 2.0}; {Bar = 4.0} |] + /// + /// input |> Array.Parallel.averageBy (fun foo -> foo.Bar) + /// + /// Evaluates to 3.0 + /// + /// + /// + /// + /// type Foo = { Bar: float } + /// + /// let input : Foo[] = [| |] + /// + /// input |> Array.Parallel.averageBy (fun foo -> foo.Bar) + /// + /// Throws ArgumentException + /// + [] + [] + val inline averageBy: + projection: ('T -> ^U) -> array: 'T[] -> ^U + when ^U: (static member (+): ^U * ^U -> ^U) and ^U: (static member DivideByInt: ^U * int -> ^U) + /// Apply the given function to each element of the array. Return /// the array comprised of the results x for each element where /// the function returns Some(x). diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl index 8d196f405f3..e373ae3440b 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl index 8e493cc60ad..e314c7263a2 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl index 2577f674bad..29f826a24ba 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl index 55ebd5ff7bb..5114bd40b1d 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl @@ -48,6 +48,20 @@ Microsoft.FSharp.Collections.ArrayModule+Parallel: Microsoft.FSharp.Core.FSharpO Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[TKey,T[]][] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: System.Tuple`2[T[],T[]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Average[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MaxBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Max[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T MinBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Min[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult ReduceBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) +Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) Microsoft.FSharp.Collections.ArrayModule+Parallel: TResult[] MapIndexed[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], T[]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs index a402c396765..ec30e724bbb 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs @@ -443,9 +443,30 @@ type ArrayModule2() = // null array let nullArr = null:string[] CheckThrowsArgumentNullException (fun () -> Array.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) - - () + [] + member this.ParallelReduce() = + let assertSameBehavior reduction arr = + Assert.AreEqual(Array.reduce reduction arr, Array.Parallel.reduce reduction arr) + + [|5;4;3;2;1|] |> assertSameBehavior (fun x y -> x+y) + [|"A"; "B"; "C" ; "D" |] |> assertSameBehavior (fun x y -> if x < y then x else y) + + CheckThrowsArgumentException (fun () -> Array.Parallel.reduce (fun x y -> x/y) [||] |> ignore) + let nullArr = null:string[] + CheckThrowsArgumentNullException (fun () -> Array.Parallel.reduce (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) + + [] + member this.ParallelReduceBy() = + let assertSameBehavior projection reduction arr = + Assert.AreEqual(arr |> Array.map projection |> Array.reduce reduction, Array.Parallel.reduceBy projection reduction arr) + + [|5;4;3;2;1|] |> assertSameBehavior (fun x -> x * 2)(fun x y -> x+y) + [|"ABCD"; "B"; "C" ; "D" |] |> assertSameBehavior (fun x -> x.Length) (Operators.Checked.(+)) + + CheckThrowsArgumentException (fun () -> Array.Parallel.reduceBy id (fun x y -> x/y) [||] |> ignore) + let nullArr = null:string[] + CheckThrowsArgumentNullException (fun () -> Array.Parallel.reduceBy id (fun (x:string) (y:string) -> x.Remove(0,y.Length)) nullArr |> ignore) [] member this.ReduceBack() = @@ -1014,6 +1035,76 @@ type ArrayModule2() = CheckThrowsArgumentNullException (fun () -> Array.sumBy float32 nullArr |> ignore) () + member private _.TestOperation opName (actual:'T) (expected:'T) = + Assert.AreEqual(expected, actual, sprintf "%s: should be %A but is %A" opName expected actual) + + [] + member this.ParallelSum() = + this.TestOperation "sum empty" (Array.Parallel.sum [||]) (0) + this.TestOperation "sum single" (Array.Parallel.sum [|42|]) (42) + this.TestOperation "sum two" (Array.Parallel.sum [|42;-21|]) (21) + this.TestOperation "sum many" (Array.Parallel.sum [|1..1000|]) ((1000*1001) / 2) + this.TestOperation "sum floats" (Array.Parallel.sum [|1.;2.;3.|]) (6.) + this.TestOperation "sum infinity" (Array.Parallel.sum [|1.;2.;infinity;3.|]) (infinity) + this.TestOperation "sum nan" (Array.Parallel.sum [|infinity;nan|] |> Double.IsNaN) (true) + + [] + member this.ParallelSumBy() = + this.TestOperation "sum_by empty" (Array.Parallel.sumBy int [||]) (0) + this.TestOperation "sum_by single" (Array.Parallel.sumBy int [|42|]) (42) + this.TestOperation "sum_by two" (Array.Parallel.sumBy int [|42;-21|]) (21) + this.TestOperation "sum_by many" (Array.Parallel.sumBy int [|1..1000|]) ((1000*1001) / 2) + this.TestOperation "sum_by floats" (Array.Parallel.sumBy float [|1.;2.;3.|]) (6.) + this.TestOperation "sum_by infinity" (Array.Parallel.sumBy float [|1.;2.;infinity;3.|]) (infinity) + this.TestOperation "sum_by abs" (Array.Parallel.sumBy abs [|1; -2; 3; -4|]) (10) + this.TestOperation "sum_by string.Length" (Array.Parallel.sumBy String.length [|"abcd";"efg";"hi";"j";""|]) (10) + + [] + member this.ParallelAverage() = + CheckThrowsArgumentException (fun () -> Array.Parallel.average [||] |> ignore) + this.TestOperation "average of 0" (Array.Parallel.average [|0.|]) (0.) + this.TestOperation "average of single" (Array.Parallel.average [|4.|]) (4.) + this.TestOperation "average of two" (Array.Parallel.average [|4.;6.|]) (5.) + + [] + member this.ParallelAverageBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.averageBy float [||] |> ignore) + this.TestOperation "average_by of 0" (Array.Parallel.averageBy id [|0.|]) (0.) + this.TestOperation "average_by of single" (Array.Parallel.averageBy id [|4.|]) (4.) + this.TestOperation "average_by of two" (Array.Parallel.averageBy id [|4.;6.|]) (5.) + this.TestOperation "average_by int>float" (Array.Parallel.averageBy float [|0..1000|]) (500.) + this.TestOperation "average_by string.Length" (Array.Parallel.averageBy (String.length >> float) [|"ab";"cdef"|]) (3.) + + [] + member this.ParallelMin() = + CheckThrowsArgumentException (fun () -> Array.Parallel.min [||] |> ignore) + this.TestOperation "min single" (Array.Parallel.min [|42|]) (42) + this.TestOperation "min many" (Array.Parallel.min [|1..100|]) (1) + this.TestOperation "min floats" (Array.Parallel.min [|1.0;-1.0;nan;infinity;-infinity|]) (-infinity) + + [] + member this.ParallelMax() = + CheckThrowsArgumentException (fun () -> Array.Parallel.max [||] |> ignore) + this.TestOperation "max single" (Array.Parallel.max [|42|]) (42) + this.TestOperation "max many" (Array.Parallel.max [|1..100|]) (100) + this.TestOperation "max floats" (Array.Parallel.max [|1.0;-1.0;nan;infinity;-infinity|]) (infinity) + + [] + member this.ParallelMinBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.minBy string [||] |> ignore) + this.TestOperation "minBy single" (Array.Parallel.minBy string [|42|]) (42) + this.TestOperation "minBy int->string" (Array.Parallel.minBy string [|5..25|]) (10) + this.TestOperation "minBy many" (Array.Parallel.minBy (fun x -> -x) [|1..100|]) (100) + this.TestOperation "minBy floats" (Array.Parallel.minBy (fun x -> 1./float x) [|1..100|]) (100) + + [] + member this.ParallelMaxBy() = + CheckThrowsArgumentException (fun () -> Array.Parallel.maxBy int [||] |> ignore) + this.TestOperation "maxBy single" (Array.Parallel.maxBy string [|42|]) (42) + this.TestOperation "maxBy many" (Array.Parallel.maxBy (fun x -> -x) [|1..100|]) (1) + this.TestOperation "maxBy floats" (Array.Parallel.maxBy (fun x -> 1./float x) [|1..100|]) (1) + + [] member this.Tl() = // integer array diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs index e22e3d019ba..7b0ac00e5db 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs @@ -44,12 +44,15 @@ let ``append is consistent`` () = smallerSizeCheck append smallerSizeCheck append +let inline roundResult res = res |> Result.map (fun (x:float) -> Math.Round(x,8)) + let averageFloat (xs : NormalFloat []) = let xs = xs |> Array.map float - let s = runAndCheckErrorType (fun () -> xs |> Seq.average) - let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.average) - let a = runAndCheckErrorType (fun () -> xs |> Array.average) - consistency "average" s l a + let s = runAndCheckErrorType (fun () -> xs |> Seq.average) |> roundResult + let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.average) |> roundResult + let a = runAndCheckErrorType (fun () -> xs |> Array.average) |> roundResult + let pa = runAndCheckErrorType (fun () -> xs |> Array.Parallel.average) |> roundResult + consistencyIncludingParallel "average" s l a pa [] let ``average is consistent`` () = @@ -58,10 +61,11 @@ let ``average is consistent`` () = let averageBy (xs : float []) f = let xs = xs |> Array.map float let f x = (f x : NormalFloat) |> float - let s = runAndCheckErrorType (fun () -> xs |> Seq.averageBy f) - let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.averageBy f) - let a = runAndCheckErrorType (fun () -> xs |> Array.averageBy f) - consistency "averageBy" s l a + let s = runAndCheckErrorType (fun () -> xs |> Seq.averageBy f) |> roundResult + let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.averageBy f) |> roundResult + let a = runAndCheckErrorType (fun () -> xs |> Array.averageBy f) |> roundResult + let pa = runAndCheckErrorType (fun () -> xs |> Array.Parallel.averageBy f) |> roundResult + consistencyIncludingParallel "averageBy" s l a pa [] @@ -85,7 +89,9 @@ let choose<'a when 'a : equality> (xs : 'a []) f = let s = xs |> Seq.choose f |> Seq.toArray let l = xs |> List.ofArray |> List.choose f |> List.toArray let a = xs |> Array.choose f - consistency "contains" s l a + let pa = xs |> Array.Parallel.choose f + + consistencyIncludingParallel "contains" s l a pa [] let ``choose is consistent`` () = @@ -116,7 +122,8 @@ let collect<'a> (xs : 'a []) f = let s = xs |> Seq.collect f |> Seq.toArray let l = xs |> List.ofArray |> List.collect (fun x -> f x |> List.ofArray) |> List.toArray let a = xs |> Array.collect f - consistency "collect" s l a + let pa = xs |> Array.Parallel.collect f + consistencyIncludingParallel "collect" s l a pa @@ -705,7 +712,8 @@ let max<'a when 'a : comparison> (xs : 'a []) = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.max) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.max) let a = runAndCheckIfAnyError (fun () -> xs |> Array.max) - consistency "max" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.max) + consistencyIncludingParallel "max" s l a pa [] let ``max is consistent`` () = @@ -717,7 +725,8 @@ let maxBy<'a when 'a : comparison> (xs : 'a []) f = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.maxBy f) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.maxBy f) let a = runAndCheckIfAnyError (fun () -> xs |> Array.maxBy f) - consistency "maxBy" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.maxBy f) + consistencyIncludingParallel "maxBy" s l a pa [] let ``maxBy is consistent`` () = @@ -729,7 +738,8 @@ let min<'a when 'a : comparison> (xs : 'a []) = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.min) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.min) let a = runAndCheckIfAnyError (fun () -> xs |> Array.min) - consistency "min" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.min) + consistencyIncludingParallel "min" s l a pa [] let ``min is consistent`` () = @@ -741,7 +751,8 @@ let minBy<'a when 'a : comparison> (xs : 'a []) f = let s = runAndCheckIfAnyError (fun () -> xs |> Seq.minBy f) let l = runAndCheckIfAnyError (fun () -> xs |> List.ofArray |> List.minBy f) let a = runAndCheckIfAnyError (fun () -> xs |> Array.minBy f) - consistency "minBy" s l a + let pa = runAndCheckIfAnyError (fun () -> xs |> Array.Parallel.minBy f) + consistencyIncludingParallel "minBy" s l a pa [] let ``minBy is consistent`` () = @@ -813,8 +824,8 @@ let ``pick is consistent`` () = let reduce<'a when 'a : equality> (xs : 'a []) f = let s = runAndCheckErrorType (fun () -> xs |> Seq.reduce f) let l = runAndCheckErrorType (fun () -> xs |> List.ofArray |> List.reduce f) - let a = runAndCheckErrorType (fun () -> xs |> Array.reduce f) - consistency "reduce" s l a + let a = runAndCheckErrorType (fun () -> xs |> Array.reduce f) + consistency "reduce" s l a [] let ``reduce is consistent`` () = @@ -1004,7 +1015,8 @@ let sum (xs : int []) = let s = run (fun () -> xs |> Seq.sum) let l = run (fun () -> xs |> Array.toList |> List.sum) let a = run (fun () -> xs |> Array.sum) - consistency "sum" s l a + let pa = run (fun () -> xs |> Array.Parallel.sum) + consistencyIncludingParallel "sum" s l a pa [] let ``sum is consistent`` () = @@ -1014,7 +1026,8 @@ let sumBy<'a> (xs : 'a []) (f:'a -> int) = let s = run (fun () -> xs |> Seq.sumBy f) let l = run (fun () -> xs |> Array.toList |> List.sumBy f) let a = run (fun () -> xs |> Array.sumBy f) - consistency "sumBy" s l a + let pa = run (fun () -> xs |> Array.Parallel.sumBy f) + consistencyIncludingParallel "sumBy" s l a pa [] let ``sumBy is consistent`` () = diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs index 53623f11548..00ae357fac6 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs @@ -377,7 +377,7 @@ type ListProperties () = let b = List.tryItem pos xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -391,7 +391,7 @@ type ListProperties () = let b = List.tryPick f xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -405,7 +405,7 @@ type ListProperties () = let b = List.tryLast xs match a with - | Success a -> b.Value = a + | Ok a -> b.Value = a | _ -> b = None [] @@ -503,7 +503,7 @@ type ListProperties () = match run (fun () -> xs |> List.indexed |> List.permute permutation) with - | Success s -> + | Ok s -> let originals = s |> List.map fst let rs = s |> List.map snd for o in originals do @@ -718,7 +718,7 @@ type ListProperties () = let a = run (fun () -> xs |> List.findIndex predicate) let b = run (fun () -> xs |> List.rev |> List.findIndexBack predicate) match a,b with - | Success a, Success b -> a = (xs.Length - b - 1) + | Ok a, Ok b -> a = (xs.Length - b - 1) | _ -> a = b [] diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs index 7d55fdcb142..ce2a299a3f1 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/Utils.fs @@ -4,29 +4,24 @@ module FSharp.Core.UnitTests.Collections.Utils open Xunit -type Result<'a> = -| Success of 'a -| Error of string - let run f = try - Success(f()) + Ok(f()) with | exn -> Error(exn.Message) let runAndCheckErrorType f = try - Success(f()) + Ok(f()) with | exn -> Error(exn.GetType().ToString()) let runAndCheckIfAnyError f = try - Success(f()) + Ok(f()) with | exn -> Error("") - let isStable sorted = sorted |> Seq.pairwise |> Seq.forall (fun ((ia, a),(ib, b)) -> if a = b then ia < ib else true) let isSorted sorted = sorted |> Seq.pairwise |> Seq.forall (fun (a,b) -> a <= b)