-
Notifications
You must be signed in to change notification settings - Fork 5
/
hlinearmap.ml
80 lines (60 loc) · 1.81 KB
/
hlinearmap.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
(* Two implementations of heterogeneous maps,
from discussions between Jeremy and me *)
module type HMAP = sig
type _ key
type _ value
type t
val fresh_key : unit -> 'a key
val empty : t
val add : t -> 'a key -> 'a value -> t
val find : t -> 'a key -> 'a value option
end
module Modern : HMAP = struct
type _ k' = ..
type (_, _) eql = Refl : ('a, 'a) eql
type 'a key = {
k : 'a k';
eq : 'b. 'b k' -> ('a, 'b) eql option
}
type _ value
let fresh_key (type a) () =
let module M = struct type _ k' += T : a k' end in
let eq : type b. b k' -> (a, b) eql option =
function M.T -> Some Refl | _ -> None in
{k = M.T; eq}
type t = Nil | Cons : 'a key * 'a value * t -> t
let empty = Nil
let add t k v = Cons (k, v, t)
let rec find : type a. t -> a key -> a value option =
fun t k ->
match t with
| Nil -> None
| Cons ({k = k'}, v, rest) ->
match k.eq k' with
| Some Refl -> Some v
| None -> find rest k
end
(* No GADT or first-class module free involved, but is much
more tricky. You may need to ponder for a while to understand
its mechanism *)
module OldSchool : HMAP = struct
type s = bool -> unit
type 'a key = ('a value -> s) * (s -> 'a value option)
and _ value
(* Consider [inj] as a pair buttons. Pressing "true" button puts value inside
box, and pressing "false" button takes the item in box outside *)
let fresh_key () =
let r = ref None in
let inj x b = r := if b then Some x else None in
let prj f = f true; let res = !r in f false; res in
(inj, prj)
type t = s list
let empty = []
let add l (inj, _) v = inj v :: l
let rec find t ((inj, prj) as k) = match t with
[] -> None
| x :: xs ->
match prj x with
Some v -> Some v
| None -> find xs k
end