Skip to content

Commit 9d0a8d8

Browse files
committed
Use a (named) type
1 parent abf8fb3 commit 9d0a8d8

File tree

1 file changed

+74
-108
lines changed

1 file changed

+74
-108
lines changed

src/FSharpPlus/Extensions/Dict.fs

Lines changed: 74 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,76 @@
11
namespace FSharpPlus
22

3-
/// Additional operations on IDictionary<'Key, 'Value>
4-
[<RequireQualifiedAccess>]
5-
module Dict =
3+
[<AutoOpen>]
4+
module Auto =
5+
open System
6+
open System.Collections
67
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-
}
278

9+
let icollection (konst: 'TValue) (source: IDictionary<'TKey,'TValue>) =
2810
{
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+
}
4122

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>) =
5024

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())
5252

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
6062

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
8769

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)
9674

9775
#if !FABLE_COMPILER
9876
open System.Linq
@@ -225,29 +203,17 @@ module Dict =
225203
for KeyValue(k, v ) in source1 do d.[k] <- v
226204
for KeyValue(k, v') in source2 do d.[k] <- match d.TryGetValue k with true, v -> f.Invoke (v, v') | _ -> v'
227205
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
251217
| _, _ -> combine()
252218

253219

0 commit comments

Comments
 (0)