type ('a,'b) decision =
| Result of 'b
| Test of ('a -> bool) * ('a, 'b) decision * ('a, 'b) decision
let decision1 = Test ( (fun x -> x > 10),
Result "Greater than 10",
Result "Smaller or equal to 10" )
let decision2 = Test ( (fun x -> x < 100),
decision1,
Result "Big")
let decision3 = Test ( (fun x -> x < 0),
Result "Negative",
decision2 )
let rec apply_decision x = function
| Result r -> r
| Test (pred, left, right) -> if pred x then apply_decision x left else apply_decision x right
let rec map_decision f = function
| Result r -> Result (f r)
| Test (pred, left, right) -> Test (pred, map_decision f left, map_decision f right)
let get_results tree =
let rec loop acu = function
| Result r -> r :: acu
| Test (_, left, right) -> loop (loop acu left) right
in
loop [] tree
let rec invert = function
| Result r -> Result r
| Test (pred, left, right) ->
let new_pred x = not (pred x) in
Test (new_pred, invert right, invert left)
type ('a,'b) edecision =
| Result of 'b
| Test of ('a -> bool) * ('a, 'b) edecision * ('a, 'b) edecision
| Error of exn
| Catch of ('a, 'b) edecision * (exn -> bool) * ('a, 'b) edecision
let edecision1 = Test ( (fun x -> x > 10),
Result "Greater than 10",
Result "Smaller or equal to 10" )
let edecision2 = Test ( (fun x -> x < 100),
edecision1,
Error Not_found )
let edecision3 = Test ( (fun x -> x < 0),
Error (Invalid_argument "Negative"),
edecision2 )
let edecision4 = Catch ( edecision3,
(function Not_found -> true | _ -> false),
Result "Too big" )
let rec apply_edecision x = function
| Result r -> r
| Test (pred, left, right) -> if pred x then apply_edecision x left else apply_edecision x right
| Error e -> raise e
| Catch (sub, epred, branch) ->
try apply_edecision x sub
with e ->
if epred e then apply_edecision x branch
else raise e