@@ -8,58 +8,72 @@ open Fable.Core
88let msgListWasEmpty = " List was empty"
99let msgListNoMatch = " List did not contain any matching elements"
1010
11- [<CustomEquality; CustomComparison>]
12- type List < 'T > when 'T : comparison =
13- { Count: int ; Values: ResizeArray < 'T > }
11+ type List < 'T when 'T: comparison >( Count : int , Values : ResizeArray < 'T >) =
12+ let mutable hashCode = None
1413
15- static member Empty =
16- { Count = 0 ; Values = ResizeArray< 'T>() }
17- static member Cons ( x : 'T , xs : 'T list ) =
14+ static member Empty = new List< 'T>( 0 , ResizeArray< 'T>())
15+ static member Cons ( x : 'T , xs : 'T list ) = xs.Add( x)
16+
17+ member _.Add ( x : 'T ) =
1818 let values =
19- if xs. Count = xs. Values.Count
20- then xs. Values
21- else xs. Values.GetRange( 0 , xs. Count)
19+ if Count = Values.Count
20+ then Values
21+ else Values.GetRange( 0 , Count)
2222 values.Add( x)
23- { Count = values.Count; Values = values }
23+ new List< 'T>( values.Count, values)
24+
25+ member _.IsEmpty = Count <= 0
26+ member _.Length = Count
27+
28+ member _.Head =
29+ if Count > 0
30+ then Values.[ Count - 1 ]
31+ else failwith msgListWasEmpty
32+
33+ member _.Tail =
34+ if Count > 0
35+ then new List< 'T>( Count - 1 , Values)
36+ else failwith msgListWasEmpty
37+
38+ member _.Item with get( index ) =
39+ Values.[ Count - 1 - index]
2440
2541 override xs.ToString () =
2642 " [" + System.String.Join( " ; " , xs) + " ]"
2743
28- override xs.GetHashCode ( ) =
29- let inline combineHash x y = ( x <<< 1 ) + y + 631
30- let mutable res = 0
31- for i = xs.Count - 1 downto 0 do
32- res <- combineHash res ( hash xs.Values .[ i ])
33- res
44+ override xs.Equals ( other : obj ) =
45+ let ys = other :?> 'T list
46+ if xs.Length <> ys.Length then false
47+ elif xs.GetHashCode () <> ys.GetHashCode () then false
48+ else Seq.forall2 ( Unchecked.equals ) xs ys
49+ // (xs :> System.IComparable).CompareTo(other) = 0
3450
35- override xs.Equals ( that : obj ) =
36- ( xs :> System.IComparable) .CompareTo( that) = 0
51+ override xs.GetHashCode () =
52+ match hashCode with
53+ | Some h -> h
54+ | None ->
55+ let inline combineHash i x y = ( x <<< 1 ) + y + 631 * i
56+ let len = min ( xs.Length - 1 ) 18 // limit the hash count
57+ let mutable h = 0
58+ for i = 0 to len do
59+ h <- combineHash i h ( hash xs.[ i])
60+ hashCode <- Some h
61+ h
3762
3863 interface System.IComparable with
39- member xs.CompareTo ( that : obj ) =
40- List.CompareWith compare xs ( that :?> 'T list)
64+ member xs.CompareTo ( other : obj ) =
65+ List.CompareWith compare xs ( other :?> 'T list)
4166
4267 interface System.Collections.Generic.IEnumerable< 'T> with
4368 member xs.GetEnumerator (): System.Collections.Generic.IEnumerator < 'T > =
44- let elems = seq { for i = xs.Count - 1 downto 0 do yield xs.Values.[ i] }
69+ let len = xs.Length - 1
70+ let elems = seq { for i = 0 to len do yield xs.[ i] }
4571 elems.GetEnumerator()
72+
4673 interface System.Collections.IEnumerable with
4774 member this.GetEnumerator (): System.Collections.IEnumerator =
4875 (( this :> System.Collections.Generic.IEnumerable< 'T>) .GetEnumerator() :> System.Collections.IEnumerator)
4976
50- member xs.Length = xs.Count
51- member xs.Head =
52- if xs.Count > 0
53- then xs.Values.[ xs.Count - 1 ]
54- else failwith msgListWasEmpty
55- member xs.Tail =
56- if xs.Count > 0
57- then { Count = xs.Count - 1 ; Values = xs.Values }
58- else failwith msgListWasEmpty
59- member xs.IsEmpty = xs.Count <= 0
60- member xs.Item with get( index ) =
61- xs.Values.[ xs.Count - 1 - index]
62-
6377 static member CompareWith ( comparer : 'T -> 'T -> int ) ( xs : 'T list ) ( ys : 'T list ): int =
6478 if obj.ReferenceEquals( xs, ys)
6579 then 0
@@ -80,9 +94,7 @@ type List<'T> when 'T : comparison =
8094
8195and 'T list when 'T : comparison = List< 'T>
8296
83- open System.Collections .Generic
84-
85- let newList ( values : ResizeArray < 'T >) = { Count = values.Count; Values = values }
97+ let newList ( values : ResizeArray < 'T >) = new List< 'T>( values.Count, values)
8698
8799let empty () = List.Empty
88100
@@ -213,7 +225,7 @@ let iterateIndexed f xs =
213225let iterateIndexed2 f xs ys =
214226 fold2 ( fun i x y -> f i x y; i + 1 ) 0 xs ys |> ignore
215227
216- let ofArray ( xs : IList < 'T >) =
228+ let ofArray ( xs : System.Collections.Generic. IList< 'T >) =
217229 let mutable res = List.Empty
218230 for i = xs.Count - 1 downto 0 do
219231 res <- cons xs.[ i] res
@@ -315,13 +327,13 @@ let choose f xs =
315327 | Some y -> cons y acc
316328 | None -> acc) List.Empty xs |> reverse
317329
318- let contains ( value : 'T ) ( xs : 'T list ) ( [<Inject>] eq : IEqualityComparer < 'T >) =
330+ let contains ( value : 'T ) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 'T >) =
319331 tryFindIndex ( fun v -> eq.Equals ( value, v)) xs |> Option.isSome
320332
321- let except ( itemsToExclude : seq < 't >) ( xs : 't list ) ( [<Inject>] eq : IEqualityComparer < 't >): 't list =
333+ let except ( itemsToExclude : seq < 't >) ( xs : 't list ) ( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 't >): 't list =
322334 if isEmpty xs then xs
323335 else
324- let cached = HashSet( itemsToExclude, eq)
336+ let cached = System.Collections.Generic. HashSet( itemsToExclude, eq)
325337 xs |> filter cached.Add
326338
327339let initialize n f =
@@ -373,16 +385,16 @@ let sortWith (comparison: 'T -> 'T -> int) (xs: 'T list): 'T list =
373385 values.Sort( System.Comparison<_>( comparison))
374386 values |> ofSeq
375387
376- let sort ( xs : 'T list ) ( [<Inject>] comparer : IComparer < 'T >): 'T list =
388+ let sort ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'T >): 'T list =
377389 sortWith ( fun x y -> comparer.Compare( x, y)) xs
378390
379- let sortBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : IComparer < 'b >): 'a list =
391+ let sortBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'b >): 'a list =
380392 sortWith ( fun x y -> comparer.Compare( projection x, projection y)) xs
381393
382- let sortDescending ( xs : 'T list ) ( [<Inject>] comparer : IComparer < 'T >): 'T list =
394+ let sortDescending ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'T >): 'T list =
383395 sortWith ( fun x y -> comparer.Compare( x, y) * - 1 ) xs
384396
385- let sortByDescending ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : IComparer < 'b >): 'a list =
397+ let sortByDescending ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'b >): 'a list =
386398 sortWith ( fun x y -> comparer.Compare( projection x, projection y) * - 1 ) xs
387399
388400let sum ( xs : 'T list ) ( [<Inject>] adder : IGenericAdder < 'T >): 'T =
@@ -391,16 +403,16 @@ let sum (xs: 'T list) ([<Inject>] adder: IGenericAdder<'T>): 'T =
391403let sumBy ( f : 'T -> 'T2 ) ( xs : 'T list ) ( [<Inject>] adder : IGenericAdder < 'T2 >): 'T2 =
392404 fold ( fun acc x -> adder.Add( acc, f x)) ( adder.GetZero()) xs
393405
394- let maxBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : IComparer < 'b >): 'a =
406+ let maxBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'b >): 'a =
395407 reduce ( fun x y -> if comparer.Compare( projection y, projection x) > 0 then y else x) xs
396408
397- let max ( li : 'a list ) ( [<Inject>] comparer : IComparer < 'a >): 'a =
409+ let max ( li : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'a >): 'a =
398410 reduce ( fun x y -> if comparer.Compare( y, x) > 0 then y else x) li
399411
400- let minBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : IComparer < 'b >): 'a =
412+ let minBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'b >): 'a =
401413 reduce ( fun x y -> if comparer.Compare( projection y, projection x) > 0 then x else y) xs
402414
403- let min ( xs : 'a list ) ( [<Inject>] comparer : IComparer < 'a >): 'a =
415+ let min ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic. IComparer< 'a >): 'a =
404416 reduce ( fun x y -> if comparer.Compare( y, x) > 0 then x else y) xs
405417
406418let average ( xs : 'T list ) ( [<Inject>] averager : IGenericAverager < 'T >): 'T =
@@ -452,11 +464,11 @@ let splitAt i (xs: 'T list) =
452464 if i > xs.Length then invalidArg " index" " The input sequence has an insufficient number of elements."
453465 take i xs, skip i xs
454466
455- let distinctBy ( projection : 'T -> 'Key ) ( xs : 'T list ) ( [<Inject>] eq : IEqualityComparer < 'Key >) =
456- let hashSet = HashSet< 'Key>( eq)
467+ let distinctBy ( projection : 'T -> 'Key ) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 'Key >) =
468+ let hashSet = System.Collections.Generic. HashSet< 'Key>( eq)
457469 xs |> filter ( projection >> hashSet.Add)
458470
459- let distinct ( xs : 'T list ) ( [<Inject>] eq : IEqualityComparer < 'T >) =
471+ let distinct ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 'T >) =
460472 distinctBy id xs eq
461473
462474let exactlyOne ( xs : 'T list ) =
@@ -465,8 +477,8 @@ let exactlyOne (xs: 'T list) =
465477 | 0 -> invalidArg " list" LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
466478 | _ -> invalidArg " list" " Input list too long"
467479
468- let groupBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : IEqualityComparer < 'Key >): ( 'Key * 'T list ) list =
469- let dict = Dictionary< 'Key, 'T list>( eq)
480+ let groupBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 'Key >): ( 'Key * 'T list ) list =
481+ let dict = System.Collections.Generic. Dictionary< 'Key, 'T list>( eq)
470482 let mutable keys = List.Empty
471483 xs |> iterate ( fun v ->
472484 let key = projection v
@@ -480,8 +492,8 @@ let groupBy (projection: 'T -> 'Key) (xs: 'T list)([<Inject>] eq: IEqualityCompa
480492 keys |> iterate ( fun key -> result <- cons ( key, reverse dict.[ key]) result)
481493 result
482494
483- let countBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : IEqualityComparer < 'Key >) =
484- let dict = Dictionary< 'Key, int>( eq)
495+ let countBy ( projection : 'T -> 'Key ) ( xs : 'T list )( [<Inject>] eq : System.Collections.Generic. IEqualityComparer< 'Key >) =
496+ let dict = System.Collections.Generic. Dictionary< 'Key, int>( eq)
485497 let mutable keys = List.Empty
486498 xs |> iterate ( fun v ->
487499 let key = projection v
0 commit comments