From 0a020aa25bec62c9333709c326392521c2a8bc24 Mon Sep 17 00:00:00 2001 From: Patrick McDonald Date: Sun, 21 Feb 2016 23:15:57 +0000 Subject: [PATCH 1/2] Implement allPairs on List, Seq and Array modules Implements fsharp/FSharpLangDesign#47 Closes Microsoft/visualfsharp#989 --- .../ArrayModule.fs | 28 ++++++++++++++++ .../CollectionModulesConsistency.fs | 12 +++++++ .../ListModule.fs | 22 +++++++++++++ .../ListProperties.fs | 32 +++++++++++++++++++ .../Microsoft.FSharp.Collections/SeqModule.fs | 27 ++++++++++++++++ .../SurfaceArea.net40.fs | 3 ++ .../SurfaceArea.portable259.fs | 3 ++ .../SurfaceArea.portable47.fs | 3 ++ .../SurfaceArea.portable7.fs | 3 ++ .../SurfaceArea.portable78.fs | 3 ++ src/fsharp/FSharp.Core/array.fs | 12 +++++++ src/fsharp/FSharp.Core/array.fsi | 8 +++++ src/fsharp/FSharp.Core/list.fs | 3 ++ src/fsharp/FSharp.Core/list.fsi | 7 ++++ src/fsharp/FSharp.Core/local.fs | 24 ++++++++++++++ src/fsharp/FSharp.Core/local.fsi | 1 + src/fsharp/FSharp.Core/seq.fs | 7 ++++ src/fsharp/FSharp.Core/seq.fsi | 8 +++++ 18 files changed, 206 insertions(+) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs index 30b04d52904..4d2cd6bb426 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs @@ -41,6 +41,34 @@ type ArrayModule() = () + [] + member this.AllPairs() = + // integer array + let resultInt = Array.allPairs [|1..3|] [|2..2..6|] + if resultInt <> [|(1,2);(1,4);(1,6) + (2,2);(2,4);(2,6) + (3,2);(3,4);(3,6)|] then Assert.Fail() + + // string array + let resultStr = Array.allPairs [|"A"; "B"; "C" ; "D" |] [|"a";"b";"c";"d"|] + if resultStr <> [|("A","a");("A","b");("A","c");("A","d") + ("B","a");("B","b");("B","c");("B","d") + ("C","a");("C","b");("C","c");("C","d") + ("D","a");("D","b");("D","c");("D","d")|] then Assert.Fail() + + // empty array + if Array.allPairs [||] [||] <> [||] then Assert.Fail() + if Array.allPairs [|1..3|] [||] <> [||] then Assert.Fail() + if Array.allPairs [||] [|1..3|] <> [||] then Assert.Fail() + + // null array + let nullArr = null:string[] + CheckThrowsArgumentNullException (fun () -> Array.allPairs nullArr nullArr |> ignore) + CheckThrowsArgumentNullException (fun () -> Array.allPairs [||] nullArr |> ignore) + CheckThrowsArgumentNullException (fun () -> Array.allPairs nullArr [||] |> ignore) + + () + [] member this.Append() = // integer array diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs index 89be33d9253..eeb64835a40 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/CollectionModulesConsistency.fs @@ -8,6 +8,18 @@ open NUnit.Framework open FsCheck open Utils +let allPairs<'a when 'a : equality> (xs : list<'a>) (xs2 : list<'a>) = + let s = xs |> Seq.allPairs xs2 + let l = xs |> List.allPairs xs2 + let a = xs |> Seq.toArray |> Array.allPairs (Seq.toArray xs2) + Seq.toArray s = a && List.toArray l = a + +[] +let ``allPairs is consistent`` () = + Check.QuickThrowOnFailure allPairs + Check.QuickThrowOnFailure allPairs + Check.QuickThrowOnFailure allPairs + let append<'a when 'a : equality> (xs : list<'a>) (xs2 : list<'a>) = let s = xs |> Seq.append xs2 let l = xs |> List.append xs2 diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs index 5a65d9eeac3..c29a47933e9 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs @@ -30,6 +30,28 @@ type ListModule() = () + [] + member this.AllPairs() = + // integer List + let resultInt = List.allPairs [1..3] [2..2..6] + Assert.AreEqual([(1,2);(1,4);(1,6) + (2,2);(2,4);(2,6) + (3,2);(3,4);(3,6)], resultInt) + + // string List + let resultStr = List.allPairs [2;3;4;5] ["b";"c";"d";"e"] + Assert.AreEqual([(2,"b");(2,"c");(2,"d");(2,"e") + (3,"b");(3,"c");(3,"d");(3,"e") + (4,"b");(4,"c");(4,"d");(4,"e") + (5,"b");(5,"c");(5,"d");(5,"e")] , resultStr) + + // empty List + let resultEpt = List.allPairs [] [] + let empTuple:(obj*obj) list = [] + Assert.AreEqual(empTuple, resultEpt) + + () + [] member this.Append() = // integer List diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs index 24a54a819c7..1cb91e71ed4 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs @@ -823,3 +823,35 @@ let ``List.sumBy calculates the sum of the mapped list`` () = Check.QuickThrowOnFailure sumBy Check.QuickThrowOnFailure sumBy Check.QuickThrowOnFailure sumBy + +let allPairsCount<'a, 'b> (xs : 'a list) (ys : 'b list) = + let pairs = List.allPairs xs ys + pairs.Length = xs.Length * ys.Length + +[] +let ``List.allPairs produces the correct number of pairs`` () = + Check.QuickThrowOnFailure allPairsCount + Check.QuickThrowOnFailure allPairsCount + Check.QuickThrowOnFailure allPairsCount + +let allPairsFst<'a, 'b when 'a : equality> (xs : 'a list) (ys : 'b list) = + let pairsFst = List.allPairs xs ys |> List.map fst + let check = xs |> List.collect (List.replicate ys.Length) + pairsFst = check + +[] +let ``List.allPairs first elements are correct`` () = + Check.QuickThrowOnFailure allPairsFst + Check.QuickThrowOnFailure allPairsFst + Check.QuickThrowOnFailure allPairsFst + +let allPairsSnd<'a, 'b when 'b : equality> (xs : 'a list) (ys : 'b list) = + let pairsFst = List.allPairs xs ys |> List.map snd + let check = [ for i in 1 .. xs.Length do yield! ys ] + pairsFst = check + +[] +let ``List.allPairs second elements are correct`` () = + Check.QuickThrowOnFailure allPairsFst + Check.QuickThrowOnFailure allPairsFst + Check.QuickThrowOnFailure allPairsFst diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs index 9d68a145884..ba61fdcf95f 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs @@ -22,6 +22,33 @@ Make sure each method works on: [] type SeqModule() = + [] + member this.AllPairs() = + + // integer Seq + let resultInt = Seq.allPairs (seq [1..7]) (seq [11..17]) + let expectedInt = + seq { for i in 1..7 do + for j in 11..17 do + yield i, j } + VerifySeqsEqual expectedInt resultInt + + // string Seq + let resultStr = Seq.allPairs (seq ["str3";"str4"]) (seq ["str1";"str2"]) + let expectedStr = seq ["str3","str1";"str3","str2";"str4","str1";"str4","str2"] + VerifySeqsEqual expectedStr resultStr + + // empty Seq + VerifySeqsEqual Seq.empty <| Seq.allPairs Seq.empty Seq.empty + VerifySeqsEqual Seq.empty <| Seq.allPairs { 1..7 } Seq.empty + VerifySeqsEqual Seq.empty <| Seq.allPairs Seq.empty { 1..7 } + + // null Seq + CheckThrowsArgumentNullException(fun() -> Seq.allPairs null null |> ignore) + CheckThrowsArgumentNullException(fun() -> Seq.allPairs null (seq [1..7]) |> ignore) + CheckThrowsArgumentNullException(fun() -> Seq.allPairs (seq [1..7]) null |> ignore) + () + [] member this.CachedSeq_Clear() = diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 1faaa8e956d..3bdacfe0b1b 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -100,6 +100,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Collections.Generic.IEnumerable Microsoft.FSharp.Collections.ArrayModule: System.String ToString() Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[System.Int32,T][] Indexed[T](T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] AllPairs[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) @@ -296,6 +297,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.FSharpList`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -432,6 +434,7 @@ Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.Int32,T]] Indexed[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T,T]] Pairwise[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] Zip[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Collections.Generic.IEnumerable`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs index bbaa70bf894..7a2246f57c8 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs @@ -87,6 +87,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Collections.Generic.IEnumerable Microsoft.FSharp.Collections.ArrayModule: System.String ToString() Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[System.Int32,T][] Indexed[T](T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] AllPairs[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) @@ -283,6 +284,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.FSharpList`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -419,6 +421,7 @@ Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.Int32,T]] Indexed[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T,T]] Pairwise[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] Zip[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Collections.Generic.IEnumerable`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs index ebf1b029557..40bfa80ecd2 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs @@ -84,6 +84,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Collections.Generic.IEnumerable Microsoft.FSharp.Collections.ArrayModule: System.String ToString() Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[System.Int32,T][] Indexed[T](T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] AllPairs[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) @@ -280,6 +281,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.FSharpList`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -416,6 +418,7 @@ Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.Int32,T]] Indexed[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T,T]] Pairwise[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] Zip[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Collections.Generic.IEnumerable`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs index 3b948aa87b2..e0d4f6b70af 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs @@ -100,6 +100,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Collections.Generic.IEnumerable Microsoft.FSharp.Collections.ArrayModule: System.String ToString() Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[System.Int32,T][] Indexed[T](T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] AllPairs[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) @@ -296,6 +297,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.FSharpList`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -432,6 +434,7 @@ Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.Int32,T]] Indexed[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T,T]] Pairwise[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] Zip[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Collections.Generic.IEnumerable`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs index 8e3e9cb566c..c8aa46a0a47 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs @@ -87,6 +87,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Collections.Generic.IEnumerable Microsoft.FSharp.Collections.ArrayModule: System.String ToString() Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[System.Int32,T][] Indexed[T](T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T,T][] Pairwise[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] AllPairs[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1,T2][] Zip[T1,T2](T1[], T2[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T1[],T2[]] Unzip[T1,T2](System.Tuple`2[T1,T2][]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[TKey,System.Int32][] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], T[]) @@ -283,6 +284,7 @@ Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[T]] Windowed[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[System.Int32,T]] Indexed[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T,T]] Pairwise[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[T1,T2]] Zip[T1,T2](Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,Microsoft.FSharp.Collections.FSharpList`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -419,6 +421,7 @@ Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] Microsoft.FSharp.Collections.SeqModule: Microsoft.FSharp.Core.FSharpOption`1[T] TryLast[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.Int32,T]] Indexed[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T,T]] Pairwise[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] AllPairs[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[T1,T2]] Zip[T1,T2](System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Collections.Generic.IEnumerable`1[T]]] GroupBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,System.Int32]] CountBy[T,TKey](Microsoft.FSharp.Core.FSharpFunc`2[T,TKey], System.Collections.Generic.IEnumerable`1[T]) diff --git a/src/fsharp/FSharp.Core/array.fs b/src/fsharp/FSharp.Core/array.fs index f3ebd6c91af..f1ce8821bcb 100644 --- a/src/fsharp/FSharp.Core/array.fs +++ b/src/fsharp/FSharp.Core/array.fs @@ -648,6 +648,18 @@ namespace Microsoft.FSharp.Collections res.[i] <- (array1.[i],array2.[i],array3.[i]) res + [] + let allPairs (array1: _[]) (array2: _[]) = + checkNonNull "array1" array1 + checkNonNull "array2" array2 + let len1 = array1.Length + let len2 = array2.Length + let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len1 * len2) + for i = 0 to len1 - 1 do + for j = 0 to len2 - 1 do + res.[i * len2 + j] <- (array1.[i],array2.[j]) + res + [] let unfold<'T,'State> (f:'State -> ('T*'State) option) (s:'State) = let res = ResizeArray<_>() diff --git a/src/fsharp/FSharp.Core/array.fsi b/src/fsharp/FSharp.Core/array.fsi index a3a37df7e5e..8248728b16c 100644 --- a/src/fsharp/FSharp.Core/array.fsi +++ b/src/fsharp/FSharp.Core/array.fsi @@ -12,6 +12,14 @@ namespace Microsoft.FSharp.Collections [] module Array = + /// Builds a new array that contains the cartesian product of the two input arrays. + /// The first input array. + /// The second input array. + /// Thrown when either of the input arrays is null. + /// The resulting array of pairs. + [] + val allPairs: array1:'T1[] -> array2:'T2[] -> ('T1 * 'T2)[] + /// Builds a new array that contains the elements of the first array followed by the elements of the second array. /// The first input array. /// The second input array. diff --git a/src/fsharp/FSharp.Core/list.fs b/src/fsharp/FSharp.Core/list.fs index f05e9097f1a..2a4121f43fb 100644 --- a/src/fsharp/FSharp.Core/list.fs +++ b/src/fsharp/FSharp.Core/list.fs @@ -616,6 +616,9 @@ namespace Microsoft.FSharp.Collections [] let collect f list = Microsoft.FSharp.Primitives.Basics.List.collect f list + [] + let allPairs list1 list2 = Microsoft.FSharp.Primitives.Basics.List.allPairs list1 list2 + [] let inline compareWith (comparer:'T -> 'T -> int) (list1: 'T list) (list2: 'T list) = let rec loop list1 list2 = diff --git a/src/fsharp/FSharp.Core/list.fsi b/src/fsharp/FSharp.Core/list.fsi index 81ff331539b..8ad306973e6 100644 --- a/src/fsharp/FSharp.Core/list.fsi +++ b/src/fsharp/FSharp.Core/list.fsi @@ -12,6 +12,13 @@ namespace Microsoft.FSharp.Collections [] module List = + /// Returns a new list that contains the cartesian product of the two input lists. + /// The first input list. + /// The second input list. + /// The resulting list of pairs. + [] + val allPairs: list1:'T1 list -> list2:'T2 list -> ('T1 * 'T2) list + /// Returns a new list that contains the elements of the first list /// followed by elements of the second. /// The first input list. diff --git a/src/fsharp/FSharp.Core/local.fs b/src/fsharp/FSharp.Core/local.fs index 6c19f151d29..aaf61a49e98 100644 --- a/src/fsharp/FSharp.Core/local.fs +++ b/src/fsharp/FSharp.Core/local.fs @@ -224,6 +224,30 @@ module internal List = collectToFreshConsTail f list cons cons.Tail + let rec allPairsToFreshConsTailSingle x ys cons = + match ys with + | [] -> cons + | (h2::t2) -> + let cons2 = freshConsNoTail (x,h2) + setFreshConsTail cons cons2 + allPairsToFreshConsTailSingle x t2 cons2 + + let rec allPairsToFreshConsTail xs ys cons = + match xs with + | [] -> setFreshConsTail cons [] + | (h::t) -> + let p = allPairsToFreshConsTailSingle h ys cons + allPairsToFreshConsTail t ys p + + let allPairs (xs:'T list) (ys:'U list) = + match xs, ys with + | _, [] -> [] + | [], _ -> [] + | _ -> + let cons = freshConsNoTail (Unchecked.defaultof<'T * 'U>) + allPairsToFreshConsTail xs ys cons + cons.Tail + // optimized mutation-based implementation. This code is only valid in fslib, where mutation of private // tail cons cells is permitted in carefully written library code. let rec filterToFreshConsTail cons f l = diff --git a/src/fsharp/FSharp.Core/local.fsi b/src/fsharp/FSharp.Core/local.fsi index 8896bf5ebed..9e3028cb1e3 100644 --- a/src/fsharp/FSharp.Core/local.fsi +++ b/src/fsharp/FSharp.Core/local.fsi @@ -7,6 +7,7 @@ open Microsoft.FSharp.Core open Microsoft.FSharp.Collections module internal List = + val allPairs : 'T1 list -> 'T2 list -> ('T1 * 'T2) list val distinctWithComparer : System.Collections.Generic.IEqualityComparer<'T> -> 'T list -> 'T list val distinctByWithComparer : System.Collections.Generic.IEqualityComparer<'Key> -> ('T -> 'Key) -> list:'T list -> 'T list when 'Key : equality val init : int -> (int -> 'T) -> 'T list diff --git a/src/fsharp/FSharp.Core/seq.fs b/src/fsharp/FSharp.Core/seq.fs index e8798fad2ca..448051fd561 100644 --- a/src/fsharp/FSharp.Core/seq.fs +++ b/src/fsharp/FSharp.Core/seq.fs @@ -1442,6 +1442,13 @@ namespace Microsoft.FSharp.Collections enumeratorR := None) (new CachedSeq<_>(cleanup, result) :> seq<_>) + [] + let allPairs source1 source2 = + checkNonNull "source1" source1 + checkNonNull "source2" source2 + let cached = cache source2 + source1 |> collect (fun x -> cached |> map (fun y -> x,y)) + [] [] let readonly (source:seq<_>) = diff --git a/src/fsharp/FSharp.Core/seq.fsi b/src/fsharp/FSharp.Core/seq.fsi index 4483ab22e00..a99bc60c7a0 100644 --- a/src/fsharp/FSharp.Core/seq.fsi +++ b/src/fsharp/FSharp.Core/seq.fsi @@ -14,6 +14,14 @@ namespace Microsoft.FSharp.Collections [] module Seq = + /// Returns a new sequence that contains the cartesian product of the two input sequences. + /// The first sequence. + /// The second sequence. + /// The result sequence. + /// Thrown when either of the input sequences is null. + [] + val allPairs: source1:seq<'T1> -> source2:seq<'T2> -> seq<'T1 * 'T2> + /// Wraps the two given enumerations as a single concatenated /// enumeration. /// From 4f76b0ebee734c324cae8d5684729093c7169144 Mon Sep 17 00:00:00 2001 From: Patrick McDonald Date: Mon, 29 Feb 2016 22:49:00 +0000 Subject: [PATCH 2/2] Fix naming error --- .../Microsoft.FSharp.Collections/ListProperties.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs index 1cb91e71ed4..5d8fbe922f8 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Collections/ListProperties.fs @@ -846,9 +846,9 @@ let ``List.allPairs first elements are correct`` () = Check.QuickThrowOnFailure allPairsFst let allPairsSnd<'a, 'b when 'b : equality> (xs : 'a list) (ys : 'b list) = - let pairsFst = List.allPairs xs ys |> List.map snd + let pairsSnd = List.allPairs xs ys |> List.map snd let check = [ for i in 1 .. xs.Length do yield! ys ] - pairsFst = check + pairsSnd = check [] let ``List.allPairs second elements are correct`` () =