|
1 | 1 | namespace FSharpPlus |
2 | 2 |
|
3 | | -/// Additional operations on IDictionary<'Key, 'Value> |
4 | | -[<RequireQualifiedAccess>] |
5 | | -module Dict = |
| 3 | +[<AutoOpen>] |
| 4 | +module Auto = |
| 5 | + open System |
| 6 | + open System.Collections |
6 | 7 | open System.Collections.Generic |
7 | | - open System.Collections.ObjectModel |
8 | | - |
9 | | - /// <summary>Creates a conceptually infinite dictionay containing the same value for all possible keys.</summary> |
10 | | - /// <param name="source">The value for all possible keys.</param> |
11 | | - let initInfinite<'TKey,'TValue> (source: 'TValue) : IDictionary<'TKey,'TValue> = |
12 | | - |
13 | | - let icollection value = |
14 | | - { |
15 | | - new ICollection<'t> with |
16 | | - member __.Contains (item: 't) = obj.ReferenceEquals (item, value) |
17 | | - member __.GetEnumerator () = (Seq.initInfinite (fun _ -> value)).GetEnumerator () :> System.Collections.IEnumerator |
18 | | - member __.GetEnumerator () = (Seq.initInfinite (fun _ -> value)).GetEnumerator () : IEnumerator<'t> |
19 | | - member __.IsReadOnly = true |
20 | | - |
21 | | - member __.Add (_item: 't) : unit = raise (System.NotImplementedException()) |
22 | | - member __.Clear () : unit = raise (System.NotImplementedException()) |
23 | | - member __.CopyTo (_array: 't [], _arrayIndex: int) : unit = raise (System.NotImplementedException()) |
24 | | - member __.Count : int = -1 |
25 | | - member __.Remove (_item: 't): bool = raise (System.NotImplementedException()) |
26 | | - } |
27 | 8 |
|
| 9 | + let icollection (konst: 'TValue) (source: IDictionary<'TKey,'TValue>) = |
28 | 10 | { |
29 | | - new IDictionary<'TKey,'TValue> with |
30 | | - member __.TryGetValue (_key: 'TKey, value: byref<'TValue>) = value <- source; true |
31 | | - member __.Count = -1 |
32 | | - member __.ContainsKey (_key: 'TKey) = true |
33 | | - member __.Contains (item: KeyValuePair<'TKey,'TValue>) = obj.ReferenceEquals (item.Value, source) |
34 | | - member __.GetEnumerator () = invalidOp "Key set is potentially infinite." : System.Collections.IEnumerator |
35 | | - member __.GetEnumerator () = invalidOp "Key set is potentially infinite." : IEnumerator<KeyValuePair<'TKey,'TValue>> |
36 | | - member __.IsReadOnly = true |
37 | | - member __.Values = icollection source |
38 | | - member __.Item |
39 | | - with get (_key: 'TKey) : 'TValue = source |
40 | | - and set (_key: 'TKey) (_: 'TValue) : unit = raise (System.NotImplementedException()) |
| 11 | + new ICollection<'TValue> with |
| 12 | + member _.Contains item = source.Values.Contains item || obj.ReferenceEquals (item, konst) |
| 13 | + member _.GetEnumerator () = (seq { yield! source.Values; yield! (Seq.initInfinite (fun _ -> konst))}).GetEnumerator () :> System.Collections.IEnumerator |
| 14 | + member _.GetEnumerator () = (seq { yield! source.Values; yield! (Seq.initInfinite (fun _ -> konst))}).GetEnumerator () : IEnumerator<'TValue> |
| 15 | + member _.IsReadOnly = true |
| 16 | + member _.Add (_item: 'TValue) : unit = raise (NotImplementedException ()) |
| 17 | + member _.Clear () : unit = raise (NotImplementedException ()) |
| 18 | + member _.CopyTo (_array: 'TValue [], _arrayIndex: int) : unit = raise (NotImplementedException ()) |
| 19 | + member _.Count : int = source.Count |
| 20 | + member _.Remove (_item: 'TValue): bool = raise (NotImplementedException ()) |
| 21 | + } |
41 | 22 |
|
42 | | - member __.Add (_key: 'TKey, _value: 'TValue) : unit = raise (System.NotImplementedException()) |
43 | | - member __.Add (_item: KeyValuePair<'TKey,'TValue>) : unit = raise (System.NotImplementedException()) |
44 | | - member __.Clear () : unit = raise (System.NotImplementedException()) |
45 | | - member __.CopyTo (_arr: KeyValuePair<'TKey,'TValue> [], _arrayIndex: int) : unit = raise (System.NotImplementedException()) |
46 | | - member __.Keys : ICollection<'TKey> = raise (System.NotImplementedException()) |
47 | | - member __.Remove (_key: 'TKey) : bool = raise (System.NotImplementedException()) |
48 | | - member __.Remove (_item: KeyValuePair<'TKey,'TValue>) : bool = raise (System.NotImplementedException()) |
49 | | - } |
| 23 | + type DefaultableDict<'TKey, 'TValue> (konst: 'TValue, source: IDictionary<'TKey,'TValue>) = |
50 | 24 |
|
51 | | - let initHybrid<'TKey,'TValue> (konst: 'TValue) (source: IDictionary<'TKey,'TValue>) : IDictionary<'TKey,'TValue> = |
| 25 | + interface IDictionary<'TKey, 'TValue> with |
| 26 | + member _.TryGetValue (key: 'TKey, value: byref<'TValue>) = |
| 27 | + match source.TryGetValue key with |
| 28 | + | true, v -> value <- v |
| 29 | + | _ -> value <- konst |
| 30 | + true |
| 31 | + member _.Count = source.Count |
| 32 | + // if typeof<'TKey>.IsValueType then |
| 33 | + // if typeof<'TKey> = typeof<bool> then 2 |
| 34 | + // else |
| 35 | + // let s = sizeof<'TKey> |
| 36 | + // if s < 4 then pown 2 (sizeof<'TKey> * 8) |
| 37 | + // else -1 // infinity |
| 38 | + // elif typeof<'TKey> = typeof<unit> then 1 |
| 39 | + // else -1 |
| 40 | + member _.ContainsKey (_key: 'TKey) = true |
| 41 | + member _.Contains (item: KeyValuePair<'TKey,'TValue>) = |
| 42 | + match source.TryGetValue item.Key with |
| 43 | + | true, v -> obj.ReferenceEquals (item.Value, v) |
| 44 | + | _ -> obj.ReferenceEquals (item.Value, konst) |
| 45 | + member _.GetEnumerator () = source.GetEnumerator () : System.Collections.IEnumerator |
| 46 | + member _.GetEnumerator () = source.GetEnumerator () : IEnumerator<KeyValuePair<'TKey,'TValue>> |
| 47 | + member _.IsReadOnly = true |
| 48 | + member _.Values = icollection konst source |
| 49 | + member _.Item |
| 50 | + with get (key: 'TKey) : 'TValue = match source.TryGetValue key with (true, v) -> v | _ -> konst |
| 51 | + and set (_key: 'TKey) (_: 'TValue) : unit = raise (System.NotImplementedException()) |
52 | 52 |
|
53 | | - let icollection (konst: 'TValue) (source: IDictionary<'TKey,'TValue>) = |
54 | | - { |
55 | | - new ICollection<'t> with |
56 | | - member __.Contains (item: 't) = source.Values.Contains item || obj.ReferenceEquals (item, konst) |
57 | | - member __.GetEnumerator () = (seq { yield! source.Values; yield! (Seq.initInfinite (fun _ -> konst))}).GetEnumerator () :> System.Collections.IEnumerator |
58 | | - member __.GetEnumerator () = (seq { yield! source.Values; yield! (Seq.initInfinite (fun _ -> konst))}).GetEnumerator () : IEnumerator<'t> |
59 | | - member __.IsReadOnly = true |
| 53 | + member _.Add (_key: 'TKey, _value: 'TValue) : unit = raise (NotImplementedException ()) |
| 54 | + member _.Add (_item: KeyValuePair<'TKey,'TValue>) : unit = raise (NotImplementedException ()) |
| 55 | + member _.Clear () : unit = raise (NotImplementedException ()) |
| 56 | + member _.CopyTo (_arr: KeyValuePair<'TKey,'TValue> [], _arrayIndex: int) : unit = raise (NotImplementedException ()) |
| 57 | + member _.Keys : ICollection<'TKey> = raise (NotImplementedException ()) |
| 58 | + member _.Remove (_key: 'TKey) : bool = raise (NotImplementedException ()) |
| 59 | + member _.Remove (_item: KeyValuePair<'TKey,'TValue>) : bool = raise (NotImplementedException ()) |
| 60 | + |
| 61 | + member _.DefaultValue = konst |
60 | 62 |
|
61 | | - member __.Add (_item: 't) : unit = raise (System.NotImplementedException()) |
62 | | - member __.Clear () : unit = raise (System.NotImplementedException()) |
63 | | - member __.CopyTo (_array: 't [], _arrayIndex: int) : unit = raise (System.NotImplementedException()) |
64 | | - member __.Count : int = -source.Count-1 |
65 | | - member __.Remove (_item: 't): bool = raise (System.NotImplementedException()) |
66 | | - } |
67 | | - { |
68 | | - new IDictionary<'TKey,'TValue> with |
69 | | - member __.TryGetValue (key: 'TKey, value: byref<'TValue>) = |
70 | | - match source.TryGetValue key with |
71 | | - | true, v -> value <- v |
72 | | - | _ -> value <- konst |
73 | | - true |
74 | | - member __.Count = -source.Count-1 |
75 | | - member __.ContainsKey (_key: 'TKey) = true |
76 | | - member __.Contains (item: KeyValuePair<'TKey,'TValue>) = |
77 | | - match source.TryGetValue item.Key with |
78 | | - | true, v -> obj.ReferenceEquals (item.Value, v) |
79 | | - | _ -> obj.ReferenceEquals (item.Value, konst) |
80 | | - member __.GetEnumerator () = source.GetEnumerator () : System.Collections.IEnumerator |
81 | | - member __.GetEnumerator () = source.GetEnumerator () : IEnumerator<KeyValuePair<'TKey,'TValue>> |
82 | | - member __.IsReadOnly = true |
83 | | - member __.Values = icollection konst source |
84 | | - member __.Item |
85 | | - with get (key: 'TKey) : 'TValue = match source.TryGetValue key with (true, v) -> v | _ -> konst |
86 | | - and set (_key: 'TKey) (_: 'TValue) : unit = raise (System.NotImplementedException()) |
| 63 | +/// Additional operations on IDictionary<'Key, 'Value> |
| 64 | +[<RequireQualifiedAccess>] |
| 65 | +module Dict = |
| 66 | + open System.Collections.Generic |
| 67 | + open System.Collections.ObjectModel |
| 68 | + open Auto |
87 | 69 |
|
88 | | - member __.Add (_key: 'TKey, _value: 'TValue) : unit = raise (System.NotImplementedException()) |
89 | | - member __.Add (_item: KeyValuePair<'TKey,'TValue>) : unit = raise (System.NotImplementedException()) |
90 | | - member __.Clear () : unit = raise (System.NotImplementedException()) |
91 | | - member __.CopyTo (_arr: KeyValuePair<'TKey,'TValue> [], _arrayIndex: int) : unit = raise (System.NotImplementedException()) |
92 | | - member __.Keys : ICollection<'TKey> = raise (System.NotImplementedException()) |
93 | | - member __.Remove (_key: 'TKey) : bool = raise (System.NotImplementedException()) |
94 | | - member __.Remove (_item: KeyValuePair<'TKey,'TValue>) : bool = raise (System.NotImplementedException()) |
95 | | - } |
| 70 | + /// <summary>Creates a conceptually infinite dictionay containing the same value for all possible keys.</summary> |
| 71 | + /// <param name="source">The value for all possible keys.</param> |
| 72 | + let initInfinite<'TKey,'TValue when 'TKey : equality> (source: 'TValue) : IDictionary<'TKey,'TValue> = new DefaultableDict<'TKey,'TValue>(source, Dictionary<'TKey,'TValue> ()) |
| 73 | + let initHybrid<'TKey,'TValue> (konst: 'TValue) (source: IDictionary<'TKey,'TValue>) : IDictionary<'TKey,'TValue> = new DefaultableDict<'TKey,'TValue>(konst, source) |
96 | 74 |
|
97 | 75 | #if !FABLE_COMPILER |
98 | 76 | open System.Linq |
@@ -225,29 +203,17 @@ module Dict = |
225 | 203 | for KeyValue(k, v ) in source1 do d.[k] <- v |
226 | 204 | for KeyValue(k, v') in source2 do d.[k] <- match d.TryGetValue k with true, v -> f.Invoke (v, v') | _ -> v' |
227 | 205 | d :> IDictionary<'Key,'Value> |
228 | | - let combineWithKonst source konst = |
229 | | - let d = Dictionary<'Key,'Value> () |
230 | | - for KeyValue(k, v) in source do d.[k] <- combiner v konst |
231 | | - d :> IDictionary<'Key,'Value> |
232 | | - let combineKonstWith konst source = |
233 | | - let d = Dictionary<'Key,'Value> () |
234 | | - for KeyValue(k, v) in source do d.[k] <- combiner konst v |
235 | | - d :> IDictionary<'Key,'Value> |
236 | | - match source1.Count, source2.Count with |
237 | | - | -1, -1 -> |
238 | | - initInfinite ( |
239 | | - combiner |
240 | | - (source1[Unchecked.defaultof<'Key>]) |
241 | | - (source2[Unchecked.defaultof<'Key>])) |
242 | | - | -1, 0 -> source1 |
243 | | - | 0, -1 -> source2 |
244 | | - | -1, x when x < -1 -> initHybrid (combiner (source1[Unchecked.defaultof<'Key>]) (source2[Unchecked.defaultof<'Key>])) (combineKonstWith (source1[Unchecked.defaultof<'Key>]) source2) |
245 | | - | x, -1 when x < -1 -> initHybrid (combiner (source1[Unchecked.defaultof<'Key>]) (source2[Unchecked.defaultof<'Key>])) (combineWithKonst source1 (source2[Unchecked.defaultof<'Key>])) |
246 | | - // Note: this is horrible and Unchecked.defaultof<'Key> is 0 for int keys, so it might not return the default value. |
247 | | - // All this hints that a specific (named) class is needed, something like DictWithDefaultValue<'Key, 'Value> then type tests can be added before reading the defaultValue property. |
248 | | - | x, y when x < -1 && y < -1 -> initHybrid (combiner (source1[Unchecked.defaultof<'Key>]) (source2[Unchecked.defaultof<'Key>])) (combine()) |
249 | | - | -1, _ -> combineKonstWith (source1[Unchecked.defaultof<'Key>]) source2 |> initHybrid (source1[Unchecked.defaultof<'Key>]) |
250 | | - | _, -1 -> combineWithKonst source1 (source2[Unchecked.defaultof<'Key>]) |> initHybrid (source2[Unchecked.defaultof<'Key>]) |
| 206 | + // let combineWithKonst source konst = |
| 207 | + // let d = Dictionary<'Key,'Value> () |
| 208 | + // for KeyValue(k, v) in source do d.[k] <- combiner v konst |
| 209 | + // d :> IDictionary<'Key,'Value> |
| 210 | + // let combineKonstWith konst source = |
| 211 | + // let d = Dictionary<'Key,'Value> () |
| 212 | + // for KeyValue(k, v) in source do d.[k] <- combiner konst v |
| 213 | + // d :> IDictionary<'Key,'Value> |
| 214 | + match source1, source2 with |
| 215 | + | (:? DefaultableDict<'Key,'Value> as s1), (:? DefaultableDict<'Key,'Value> as s2) -> initHybrid (combiner s1.DefaultValue s2.DefaultValue) (combine()) |
| 216 | + | s, empty | empty, s when empty.Count = 0 -> s |
251 | 217 | | _, _ -> combine() |
252 | 218 |
|
253 | 219 |
|
|
0 commit comments