-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathnmap.ml
105 lines (85 loc) · 3.89 KB
/
nmap.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
open Signatures
module Key = N
(* An intrinsically well-typed dependently-typed map whose domain is type-level nat, and whose codomain type can be parametrized by the key and by an extra parameter. *)
module Make (F : Fam2) : MAP with module Key := N and module F := F = struct
(* We represent such a map as the list of its possible values, with 0 coming first and then 1 and so on, stopping when there are no more entries. To get things to be well-typed, the sub-lists must be parametrized by the distance into the map that we've already descended. Later we will define "the" type of maps to be the ones parametrized by zero. *)
type ('b, 'n) map = Entry of ('b, 'n) F.t option * ('b, 'n N.suc) map | Empty
(* Similarly, the operations are naturally defined on the generic version, and then specialized for the caller to the ones parametrized by zero. *)
module Internal = struct
let rec find_opt : type b m n mn. (m, n, mn) Fwn.bplus -> (b, m) map -> (b, mn) F.t option =
fun mn map ->
match map with
| Empty -> None
| Entry (x, xs) -> (
match mn with
| Zero -> x
| Suc mn -> find_opt mn xs)
let rec add : type b m n mn. (m, n, mn) Fwn.bplus -> (b, mn) F.t -> (b, m) map -> (b, m) map =
fun mn x map ->
match (mn, map) with
| Zero, Empty -> Entry (Some x, Empty)
| Zero, Entry (_, xs) -> Entry (Some x, xs)
| Suc mn, Empty -> Entry (None, add mn x Empty)
| Suc mn, Entry (y, xs) -> Entry (y, add mn x xs)
let rec update :
type b m n mn.
(m, n, mn) Fwn.bplus ->
((b, mn) F.t option -> (b, mn) F.t option) ->
(b, m) map ->
(b, m) map =
fun mn f map ->
match (mn, map) with
| Zero, Empty -> Entry (f None, Empty)
| Zero, Entry (x, xs) -> Entry (f x, xs)
| Suc mn, Empty -> Entry (None, update mn f Empty)
| Suc mn, Entry (y, xs) -> Entry (y, update mn f xs)
let rec remove : type b m n mn. (m, n, mn) Fwn.bplus -> (b, m) map -> (b, m) map =
fun mn map ->
match map with
| Empty -> Empty
| Entry (x, xs) -> (
match mn with
| Zero -> Entry (None, xs)
| Suc mn -> Entry (x, remove mn xs))
type 'a mapper = { map : 'g. 'g N.t -> ('a, 'g) F.t -> ('a, 'g) F.t }
let rec map : type a m. a mapper -> m N.t -> (a, m) map -> (a, m) map =
fun f m mp ->
match mp with
| Empty -> Empty
| Entry (x, xs) -> Entry (Option.map (f.map m) x, map f (N.suc m) xs)
type 'a iterator = { it : 'g. 'g N.t -> ('a, 'g) F.t -> unit }
let rec iter : type a m. a iterator -> m N.t -> (a, m) map -> unit =
fun f m map ->
match map with
| Empty -> ()
| Entry (x, xs) ->
Option.iter (f.it m) x;
iter f (N.suc m) xs
end
let find_opt : type b m n. n N.t -> (b, N.zero) map -> (b, n) F.t option =
fun n map ->
let (Of_bwn (_, mn)) = Fwn.of_bwn n in
Internal.find_opt mn map
let add : type b m n. n N.t -> (b, n) F.t -> (b, N.zero) map -> (b, N.zero) map =
fun n x map ->
let (Of_bwn (_, mn)) = Fwn.of_bwn n in
Internal.add mn x map
let update :
type b m n.
n N.t -> ((b, n) F.t option -> (b, n) F.t option) -> (b, N.zero) map -> (b, N.zero) map =
fun n f map ->
let (Of_bwn (_, mn)) = Fwn.of_bwn n in
Internal.update mn f map
let remove : type b m n. n N.t -> (b, N.zero) map -> (b, N.zero) map =
fun n map ->
let (Of_bwn (_, mn)) = Fwn.of_bwn n in
Internal.remove mn map
type 'a mapper = { map : 'g. 'g N.t -> ('a, 'g) F.t -> ('a, 'g) F.t }
let map : type b. b mapper -> (b, N.zero) map -> (b, N.zero) map =
fun f mp -> Internal.map { map = f.map } N.zero mp
type 'a iterator = { it : 'g. 'g N.t -> ('a, 'g) F.t -> unit }
let iter : type b. b iterator -> (b, N.zero) map -> unit =
fun f m -> Internal.iter { it = f.it } N.zero m
type 'b t = ('b, N.zero) map
let empty : type b. b t = Empty
end