-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheff.ml
135 lines (116 loc) · 3.45 KB
/
eff.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
type empty
effect Fail : empty
effect Decide : bool
let fail () = Obj.magic (perform Fail)
let decide () = perform Decide
let chooseTrue x = match x with
| x -> x
| effect Decide k -> continue k true
let chooseMax x = match x with
| x -> x
| effect Decide k ->
max (continue (Obj.clone_continuation k) true) (continue (Obj.clone_continuation k) false)
let chooseAll x = match x with
| x -> [x]
| effect Fail _ -> []
| effect Decide k ->
(continue (Obj.clone_continuation k) true) @ (continue (Obj.clone_continuation k) false)
let backtrack x = match x () with
| x -> x
| effect Decide k ->
match continue (Obj.clone_continuation k) false with
| x -> x
| effect Fail _ -> continue (Obj.clone_continuation k) true
type d = Good | Bad
type tree =
| Leaf of d
| Node of tree * tree
type direction = Left | Right
let rec findGood acc = function
| Leaf Good -> List.rev acc
| Leaf Bad -> fail ()
| Node (left, right) ->
if decide ()
then findGood (Left :: acc) left
else findGood (Right :: acc) right
let findGood2 tree =
let module D = struct exception DeadEnd end in
let open D in
let rec findGood2 acc tree =
let rec loop = function
| Leaf Good -> List.rev acc
| Leaf Bad -> raise DeadEnd
| Node (left, right) ->
match findGood2 (Left :: acc) left with
| result -> result
| exception DeadEnd -> findGood2 (Right :: acc) right
in
loop tree
in
match findGood2 [] tree with
| k -> k
| exception DeadEnd -> []
let tree =
Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Leaf Bad)),
Leaf Bad)))),
Leaf Bad)))),
Leaf Bad)))),
Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Node (
Node (Leaf Bad, Leaf Bad),
Node (
Node (
Leaf Bad,
Node (Leaf Bad, Leaf Bad)),
Leaf Bad)))),
Leaf Bad)))),
Leaf Bad)))),
Leaf Bad))))
let result = fun () -> findGood [] tree
let actual =
match backtrack result with
| k -> k
| effect Fail _ -> []
let actual2 = findGood2 tree
let () =
let f = function Left -> print_endline "Left" | Right -> print_endline "Right" in
(match actual=actual2 with
| true -> print_endline "they are equal"
| false -> print_endline "they are NOT equal");
actual2 |> List.iter f;
print_endline "";
actual |> List.iter f