-
Notifications
You must be signed in to change notification settings - Fork 0
/
graph.ml
40 lines (33 loc) · 1.04 KB
/
graph.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
open Std
let acyclic_walk (type k) (module M: Hashtbl.Key with type t = k) key build =
let module E = struct exception Cycle of k list end in
let table = Hashtbl.create (module M) in
let seen = Hash_set.create (module M) in
let rec walk stack key =
let stack = key :: stack in
match (Hashtbl.find table key, Hash_set.mem seen key) with
| (Some data, _) -> data
| (None, true) -> raise (E.Cycle (List.rev stack))
| (None, false) ->
Hash_set.add seen key;
let data = build (walk stack) key in
Hashtbl.set table ~key ~data;
data
in
try Ok (walk [] key, table)
with | E.Cycle cycle -> Error cycle
;;
let cyclic_walk (type k) (module M: Hashtbl.Key with type t = k) key empty build =
let table = Hashtbl.create (module M) in
let rec walk key =
match Hashtbl.find table key with
| Some data -> data
| None ->
let data = empty key in
Hashtbl.set table ~key ~data;
let data = build walk data in
Hashtbl.set table ~key ~data;
data
in
(walk key, table)
;;