diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index d0d608f1190..a162c5d2e7f 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -3517,6 +3517,7 @@ namespace Microsoft.FSharp.Collections //------------------------------------------------------------------------- open System + open System.Collections open System.Collections.Generic open System.Diagnostics open Microsoft.FSharp.Core @@ -3529,7 +3530,7 @@ namespace Microsoft.FSharp.Collections [>)>] [] [] - [] + [] [] type List<'T> = | ([]) : 'T list @@ -3538,6 +3539,11 @@ namespace Microsoft.FSharp.Collections interface System.Collections.IEnumerable interface System.Collections.Generic.IReadOnlyCollection<'T> interface System.Collections.Generic.IReadOnlyList<'T> + interface IComparable + interface IComparable> + interface IEquatable> + interface IStructuralComparable + interface IStructuralEquatable and 'T list = List<'T> @@ -3699,6 +3705,7 @@ namespace Microsoft.FSharp.Collections static member Empty : 'T list = [] static member Cons(head,tail) : 'T list = head :: tail + override x.ToString() = match x with | [] -> "[]" @@ -3719,6 +3726,41 @@ namespace Microsoft.FSharp.Collections [] member l.GetReverseIndex(_: int, offset: int) = l.Length - offset - 1 + + override this.GetHashCode() = + let len = PrivateListHelpers.lengthAcc 0 this + let mutable i = len - 1 + if i > LanguagePrimitives.HashCompare.defaultHashNodes then + i <- LanguagePrimitives.HashCompare.defaultHashNodes // Limit the hash + + let rec loop l i acc = + match l with + | [] -> acc + | h::t -> + if i >= 0 then + loop t (i - 1) (LanguagePrimitives.HashCompare.HashCombine i acc (LanguagePrimitives.GenericHash h)) + else + acc + + loop this i 0 + + override this.Equals(other) = + let rec loop x y = + match x, y with + | [], [] -> true + | _, [] -> false + | [], _ -> false + | xHead :: xTail, yHead :: yTail -> + if not (GenericEqualityER xHead yHead) then + false + else + loop xTail yTail + + match other with + | :? List<'T> as o -> + loop this o + | _ -> + false interface IEnumerable<'T> with member l.GetEnumerator() = PrivateListHelpers.mkListEnumerator l @@ -3732,6 +3774,109 @@ namespace Microsoft.FSharp.Collections interface IReadOnlyList<'T> with member l.Item with get(index) = l.[index] + interface IComparable with + member this.CompareTo(other) = + let rec loop l1 l2 = + match l1, l2 with + | [], [] -> 0 + | _, [] -> 1 + | [], _ -> -1 + | h1 :: t1, h2 :: t2 -> + let res = GenericComparison h1 h2 + if res <> 0 then + res + else + loop t1 t2 + + match other with + | :? List<'T> as o -> + loop this o + | _ -> 0 + + interface IComparable> with + member this.CompareTo(other) = + let rec loop l1 l2 = + match l1, l2 with + | [], [] -> 0 + | _, [] -> 1 + | [], _ -> -1 + | h1 :: t1, h2 :: t2 -> + let res = GenericComparison h1 h2 + if res <> 0 then + res + else + loop t1 t2 + loop this other + + interface IEquatable> with + member this.Equals(other) = + let rec loop x y = + match x, y with + | [], [] -> true + | _, [] -> false + | [], _ -> false + | xHead :: xTail, yHead :: yTail -> + if not (GenericEqualityER xHead yHead) then + false + else + loop xTail yTail + + loop this other + + interface IStructuralComparable with + member this.CompareTo(other, comparer) = + let rec loop l1 l2 = + match l1, l2 with + | [], [] -> 0 + | _, [] -> 1 + | [], _ -> -1 + | h1 :: t1, h2 :: t2 -> + let res = comparer.Compare(h1, h2) + if res <> 0 then + res + else + loop t1 t2 + + match other with + | :? List<'T> as o -> + loop this o + | _ -> 0 + + interface IStructuralEquatable with + member this.Equals(other, comparer) = + let rec loop x y = + match x, y with + | [], [] -> true + | _, [] -> false + | [], _ -> false + | xHead :: xTail, yHead :: yTail -> + if not (comparer.Equals(xHead, yHead)) then + false + else + loop xTail yTail + + match other with + | :? List<'T> as o -> + loop this o + | _ -> false + + member this.GetHashCode(comparer) = + let len = PrivateListHelpers.lengthAcc 0 this + let mutable i = len - 1 + if i > LanguagePrimitives.HashCompare.defaultHashNodes then + i <- LanguagePrimitives.HashCompare.defaultHashNodes // Limit the hash + + let rec loop l i acc = + match l with + | [] -> acc + | h::t -> + if i >= 0 then + loop t (i - 1) (LanguagePrimitives.HashCompare.HashCombine i acc (comparer.GetHashCode(h))) + else + acc + + loop this i 0 + type seq<'T> = IEnumerable<'T> diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 3c35192188e..b5faa66259b 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -1998,7 +1998,7 @@ namespace Microsoft.FSharp.Collections /// the notation [1;2;3]. Use the values in the List module to manipulate /// values of this type, or pattern match against the values directly. [] - [] + [] [] type List<'T> = | ([]) : 'T list @@ -2048,6 +2048,11 @@ namespace Microsoft.FSharp.Collections interface IEnumerable interface IReadOnlyCollection<'T> interface IReadOnlyList<'T> + interface IComparable + interface IComparable> + interface IEquatable> + interface IStructuralComparable + interface IStructuralEquatable /// An abbreviation for the type of immutable singly-linked lists. ///