1- module List
1+ module LinkedList
22
33open Fable.Core
44
@@ -16,18 +16,26 @@ module SR =
1616[<CustomEquality; CustomComparison>]
1717// [<CompiledName("FSharpList`1")>]
1818type List < 'T when 'T: comparison > =
19- { head: 'T ; tail: List < 'T > option }
19+ { head: 'T ; mutable tail: List < 'T > option }
2020
2121 static member inline Empty : List < 'T > = { head = Unchecked.defaultof< 'T>; tail = None }
2222 static member inline Cons ( x : 'T , xs : 'T list ) = { head = x; tail = Some xs }
2323
24- member xs.IsEmpty = xs.tail.IsNone
24+ static member inline internal ConsNoTail ( x : 'T ) = { head = x; tail = None }
25+ member inline internal xs.SetConsTail ( t : 'T list ) = xs.tail <- Some t
26+ member inline internal xs.AppendConsNoTail ( x : 'T ) =
27+ let t = List.ConsNoTail x
28+ xs.SetConsTail t
29+ t
30+
31+ member inline xs.IsEmpty = xs.tail.IsNone
2532
2633 member xs.Length =
27- let rec loop i = function
34+ let rec loop i xs =
35+ match xs.tail with
2836 | None -> i
29- | Some t -> loop ( i + 1 ) t.tail
30- loop 0 xs.tail
37+ | Some t -> loop ( i + 1 ) t
38+ loop 0 xs
3139
3240 member xs.Head =
3341 match xs.tail with
@@ -56,20 +64,40 @@ type List<'T when 'T: comparison> =
5664 then true
5765 else
5866 let ys = other :?> 'T list
59- Seq.forall2 ( Unchecked.equals) xs ys
67+ let rec loop xs ys =
68+ match xs.tail, ys.tail with
69+ | None, None -> true
70+ | None, Some _ -> false
71+ | Some _, None -> false
72+ | Some xt, Some yt ->
73+ if xs.head = ys.head
74+ then loop xt yt
75+ else false
76+ loop xs ys
6077
6178 override xs.GetHashCode () =
6279 let inline combineHash i x y = ( x <<< 1 ) + y + 631 * i
63- let mutable i = 0
64- let mutable h = 0
65- for x in xs do
66- i <- i + 1
67- h <- combineHash i h ( hash x)
68- h
80+ let iMax = 18 // limit the hash
81+ let rec loop i h ( xs : 'T list ) =
82+ match xs.tail with
83+ | None -> h
84+ | Some t ->
85+ if i > iMax then h
86+ else loop ( i + 1 ) ( combineHash i h ( hash xs.head)) t
87+ loop 0 0 xs
6988
7089 interface System.IComparable with
7190 member xs.CompareTo ( other : obj ) =
72- Seq.compareWith compare xs ( other :?> 'T list)
91+ let ys = other :?> 'T list
92+ let rec loop xs ys =
93+ match xs.tail, ys.tail with
94+ | None, None -> 0
95+ | None, Some _ -> - 1
96+ | Some _, None -> 1
97+ | Some xt, Some yt ->
98+ let c = compare xs.head ys.head
99+ if c = 0 then loop xt yt else c
100+ loop xs ys
73101
74102 interface System.Collections.Generic.IEnumerable< 'T> with
75103 member xs.GetEnumerator (): System.Collections.Generic.IEnumerator < 'T > =
@@ -138,70 +166,110 @@ let last (xs: 'T list) =
138166 | None -> failwith SR.inputListWasEmpty
139167
140168let compareWith ( comparer : 'T -> 'T -> int ) ( xs : 'T list ) ( ys : 'T list ): int =
141- Seq.compareWith comparer xs ys
142-
143- let fold ( folder : 'acc -> 'T -> 'acc ) ( state : 'acc ) ( xs : 'T list ) =
169+ let rec loop ( xs : 'T list ) ( ys : 'T list ) =
170+ match xs.IsEmpty, ys.IsEmpty with
171+ | true , true -> 0
172+ | true , false -> - 1
173+ | false , true -> 1
174+ | false , false ->
175+ let c = comparer xs.Head ys.Head
176+ if c = 0 then loop xs.Tail ys.Tail else c
177+ loop xs ys
178+
179+ let fold ( folder : 'State -> 'T -> 'State ) ( state : 'State ) ( xs : 'T list ) =
144180 let rec loop acc ( ys : 'T list ) =
145181 if ys.IsEmpty then acc
146182 else loop ( folder acc ys.Head) ys.Tail
147183 loop state xs
148184
149- let foldBack ( folder : 'T -> 'acc -> 'acc ) ( xs : 'T list ) ( state : 'acc ) =
185+ let foldBack ( folder : 'T -> 'State -> 'State ) ( xs : 'T list ) ( state : 'State ) =
150186 Seq.foldBack folder xs state
151187
152- let foldIndexed ( folder : int -> 'acc -> 'T -> 'acc ) ( state : 'acc ) ( xs : 'T list ) =
188+ let foldIndexed ( folder : int -> 'State -> 'T -> 'State ) ( state : 'State ) ( xs : 'T list ) =
153189 let rec loop i acc ( ys : 'T list ) =
154190 if ys.IsEmpty then acc
155191 else loop ( i + 1 ) ( folder i acc ys.Head) ys.Tail
156192 loop 0 state xs
157193
158- let reverse ( xs : 'a list ) =
194+ let reverse ( xs : 'T list ) =
159195 fold ( fun acc x -> List.Cons( x, acc)) List.Empty xs
160196
161- let toSeq ( xs : 'a list ): 'a seq =
162- xs :> System.Collections.Generic.IEnumerable< 'a >
197+ let toSeq ( xs : 'T list ): 'T seq =
198+ xs :> System.Collections.Generic.IEnumerable< 'T >
163199
164- let ofSeq ( xs : 'a seq ): 'a list =
165- Seq.fold ( fun acc x -> List.Cons( x, acc)) List.Empty xs
166- |> reverse
200+ let ofArrayWithTail ( xs : System.Collections.Generic.IList < 'T >) ( tail : 'T list ) =
201+ let mutable res = tail
202+ for i = xs.Count - 1 downto 0 do
203+ res <- List.Cons( xs.[ i], res)
204+ res
167205
168- let concat ( lists : seq < 'a list >) =
206+ let ofArray ( xs : System.Collections.Generic.IList < 'T >) =
207+ ofArrayWithTail xs List.Empty
208+
209+ let ofSeq ( xs : seq < 'T >): 'T list =
210+ match xs with
211+ | :? list< 'T> as lst -> lst
212+ | :? array< 'T> as arr -> ofArray arr
213+ | _ ->
214+ let root = List.Empty
215+ let mutable node = root
216+ for x in xs do
217+ node <- node.AppendConsNoTail x
218+ node.SetConsTail List.Empty
219+ root.Tail
220+
221+ let concat ( lists : seq < 'T list >) =
169222 Seq.fold ( fold ( fun acc x -> List.Cons( x, acc))) List.Empty lists
170223 |> reverse
171224
172- let fold2 f ( state : 'acc ) ( xs : 'a list ) ( ys : 'b list ) =
225+ let fold2 f ( state : 'State ) ( xs : 'T list ) ( ys : 'U list ) =
173226 Seq.fold2 f state xs ys
174227
175- let foldBack2 f ( xs : 'a list ) ( ys : 'b list ) ( state : 'acc ) =
228+ let foldBack2 f ( xs : 'T list ) ( ys : 'U list ) ( state : 'State ) =
176229 Seq.foldBack2 f xs ys state
177230
178- let unfold ( gen : 'acc -> ( 'T * 'acc ) option ) ( state : 'acc ) =
179- let rec loop st acc =
231+ let unfold ( gen : 'State -> ( 'T * 'State ) option ) ( state : 'State ) =
232+ let rec loop st ( node : 'T list ) =
180233 match gen st with
181- | None -> reverse acc
182- | Some ( x, st) -> loop st ( List.Cons( x, acc))
183- loop state List.Empty
234+ | None -> node.SetConsTail List.Empty
235+ | Some ( x, st) -> loop st ( node.AppendConsNoTail x)
236+ let root = List.Empty
237+ loop state root
238+ root.Tail
184239
185- let scan f ( state : 'acc ) ( xs : 'a list ) =
240+ let scan f ( state : 'State ) ( xs : 'T list ) =
186241 Seq.scan f state xs |> ofSeq
187242
188- let scanBack f ( xs : 'a list ) ( state : 'acc ) =
243+ let scanBack f ( xs : 'T list ) ( state : 'State ) =
189244 Seq.scanBack f xs state |> ofSeq
190245
191- let append ( xs : 'a list ) ( ys : 'a list ) =
246+ let append ( xs : 'T list ) ( ys : 'T list ) =
192247 fold ( fun acc x -> List.Cons( x, acc)) ys ( reverse xs)
193248
194- let collect ( f : 'a -> 'b list ) ( xs : 'a list ) =
195- Seq.collect f xs |> ofSeq
196-
197- let mapIndexed ( f : int -> 'a -> 'b ) ( xs : 'a list ) =
198- foldIndexed ( fun i acc x -> List.Cons( f i x, acc)) List.Empty xs
199- |> reverse
200-
201- let map ( f : 'a -> 'b ) ( xs : 'a list ) =
249+ let collect ( f : 'T -> 'U list ) ( xs : 'T list ) =
250+ let root = List.Empty
251+ let mutable node = root
252+ let mutable ys = xs
253+ while not ys.IsEmpty do
254+ let mutable zs = f ys.Head
255+ while not zs.IsEmpty do
256+ node <- node.AppendConsNoTail zs.Head
257+ zs <- zs.Tail
258+ ys <- ys.Tail
259+ node.SetConsTail List.Empty
260+ root.Tail
261+
262+ let mapIndexed ( f : int -> 'T -> 'U ) ( xs : 'T list ) =
263+ let root = List.Empty
264+ let folder i ( acc : 'U list ) x = acc.AppendConsNoTail ( f i x)
265+ let node = foldIndexed folder root xs
266+ node.SetConsTail List.Empty
267+ root.Tail
268+
269+ let map ( f : 'T -> 'U ) ( xs : 'T list ) =
202270 mapIndexed ( fun i x -> f x) xs
203271
204- let indexed ( xs : 'a list ) =
272+ let indexed xs =
205273 mapIndexed ( fun i x -> ( i, x)) xs
206274
207275let map2 f xs ys =
@@ -235,26 +303,17 @@ let iterateIndexed f xs =
235303let iterateIndexed2 f xs ys =
236304 fold2 ( fun i x y -> f i x y; i + 1 ) 0 xs ys |> ignore
237305
238- let ofArrayWithTail ( xs : System.Collections.Generic.IList < 'T >) ( tail : 'T list ) =
239- let mutable res = tail
240- for i = xs.Count - 1 downto 0 do
241- res <- List.Cons( xs.[ i], res)
242- res
243-
244- let ofArray ( xs : System.Collections.Generic.IList < 'T >) =
245- ofArrayWithTail xs List.Empty
246-
247- let tryPickIndexed ( f : int -> 'a -> 'b option ) ( xs : 'a list ) =
248- let rec loop i ( ys : 'a list ) =
306+ let tryPickIndexed ( f : int -> 'T -> 'U option ) ( xs : 'T list ) =
307+ let rec loop i ( ys : 'T list ) =
249308 if ys.IsEmpty then None
250309 else
251310 match f i ys.Head with
252311 | Some _ as res -> res
253312 | None -> loop ( i + 1 ) ys.Tail
254313 loop 0 xs
255314
256- let tryPickIndexedBack ( f : int -> 'a -> 'b option ) ( xs : 'a list ) =
257- let rec loop i acc ( ys : 'a list ) =
315+ let tryPickIndexedBack ( f : int -> 'T -> 'U option ) ( xs : 'T list ) =
316+ let rec loop i acc ( ys : 'T list ) =
258317 if ys.IsEmpty then acc
259318 else
260319 let result =
@@ -316,15 +375,15 @@ let findIndexBack f xs: int =
316375 | None -> indexNotFound()
317376 | Some x -> x
318377
319- let tryItem n ( xs : 'a list ) =
320- let rec loop i ( ys : 'a list ) =
378+ let tryItem n ( xs : 'T list ) =
379+ let rec loop i ( ys : 'T list ) =
321380 if ys.IsEmpty then None
322381 else
323382 if i = n then Some ys.Head
324383 else loop ( i + 1 ) ys.Tail
325384 loop 0 xs
326385
327- let item n ( xs : 'a list ) = xs.Item( n)
386+ let item n ( xs : 'T list ) = xs.Item( n)
328387
329388let filter f xs =
330389 fold ( fun acc x ->
@@ -348,8 +407,8 @@ let choose f xs =
348407let contains ( value : 'T ) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'T >) =
349408 tryFindIndex ( fun v -> eq.Equals ( value, v)) xs |> Option.isSome
350409
351- let except ( itemsToExclude : seq < 't >) ( xs : 't list ) ( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 't >): 't list =
352- if isEmpty xs then xs
410+ let except ( itemsToExclude : seq < 'T >) ( xs : 'T list ) ( [<Inject>] eq : System.Collections.Generic.IEqualityComparer < 'T >) =
411+ if xs.IsEmpty then xs
353412 else
354413 let cached = System.Collections.Generic.HashSet( itemsToExclude, eq)
355414 xs |> filter cached.Add
@@ -363,12 +422,12 @@ let initialize n f =
363422let replicate n x =
364423 initialize n ( fun _ -> x)
365424
366- let reduce f xs =
367- if isEmpty xs then invalidOp SR.inputListWasEmpty
425+ let reduce f ( xs : 'T list ) =
426+ if xs.IsEmpty then invalidOp SR.inputListWasEmpty
368427 else fold f ( head xs) ( tail xs)
369428
370- let reduceBack f xs =
371- if isEmpty xs then invalidOp SR.inputListWasEmpty
429+ let reduceBack f ( xs : 'T list ) =
430+ if xs.IsEmpty then invalidOp SR.inputListWasEmpty
372431 else foldBack f ( tail xs) ( head xs)
373432
374433let forAll f xs =
@@ -380,7 +439,7 @@ let forAll2 f xs ys =
380439let exists f xs =
381440 tryFindIndex f xs |> Option.isSome
382441
383- let rec exists2 f ( xs : 'a list ) ( ys : 'b list ) =
442+ let rec exists2 f ( xs : 'T list ) ( ys : 'U list ) =
384443 match xs.IsEmpty, ys.IsEmpty with
385444 | true , true -> false
386445 | false , false -> f xs.Head ys.Head || exists2 f xs.Tail ys.Tail
@@ -406,28 +465,28 @@ let sortWith (comparison: 'T -> 'T -> int) (xs: 'T list): 'T list =
406465let sort ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T list =
407466 sortWith ( fun x y -> comparer.Compare( x, y)) xs
408467
409- let sortBy ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'b >): 'a list =
468+ let sortBy ( projection : 'T -> 'U ) ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'U >): 'T list =
410469 sortWith ( fun x y -> comparer.Compare( projection x, projection y)) xs
411470
412471let sortDescending ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T list =
413472 sortWith ( fun x y -> comparer.Compare( x, y) * - 1 ) xs
414473
415- let sortByDescending ( projection : 'a -> 'b ) ( xs : 'a list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'b >): 'a list =
474+ let sortByDescending ( projection : 'T -> 'U ) ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'U >): 'T list =
416475 sortWith ( fun x y -> comparer.Compare( projection x, projection y) * - 1 ) xs
417476
418477let sum ( xs : 'T list ) ( [<Inject>] adder : IGenericAdder < 'T >): 'T =
419478 fold ( fun acc x -> adder.Add( acc, x)) ( adder.GetZero()) xs
420479
421- let sumBy ( f : 'T -> 'T2 ) ( xs : 'T list ) ( [<Inject>] adder : IGenericAdder < 'T2 >): 'T2 =
480+ let sumBy ( f : 'T -> 'U ) ( xs : 'T list ) ( [<Inject>] adder : IGenericAdder < 'U >): 'U =
422481 fold ( fun acc x -> adder.Add( acc, f x)) ( adder.GetZero()) xs
423482
424- let maxBy ( projection : 'a -> 'b ) xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'b >): 'a =
483+ let maxBy ( projection : 'T -> 'U ) xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'U >): 'T =
425484 reduce ( fun x y -> if comparer.Compare( projection y, projection x) > 0 then y else x) xs
426485
427- let max xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'a >): 'a =
486+ let max xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T =
428487 reduce ( fun x y -> if comparer.Compare( y, x) > 0 then y else x) xs
429488
430- let minBy ( projection : 'a -> 'b ) xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'b >): 'a =
489+ let minBy ( projection : 'T -> 'U ) xs ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'U >): 'T =
431490 reduce ( fun x y -> if comparer.Compare( projection y, projection x) > 0 then x else y) xs
432491
433492let min ( xs : 'T list ) ( [<Inject>] comparer : System.Collections.Generic.IComparer < 'T >): 'T =
0 commit comments