type arg = bool * int * int ;; let choose (arg:arg) : int -> int = let (b, x, y) = arg in if b then (fun n -> n + x + y) else (fun n -> n + y) ;; type f1_env = {x1:int; y1:int} ;; type f2_env = {y2:int} ;; type env = F1 of f1_env | F2 of f2_env ;; type closure = (int * env -> int) * env ;; let f1 ((n,env) : int * env) : int = match env with F1 e -> n + e.x1 + e.y1 | F2 _ -> failwith "this is the wrong environment for this function!!" ;; let f2 ((n,env) : int * env) : int = match env with F1 _ -> failwith "this is the wrong environment for this function!!" | F2 e -> n + e.y2 ;; (* this version of choose returns a closure, * which is a pair of code and environment *) let choose2 (arg : arg) : closure = let (b, x, y) = arg in if b then (f1, F1 {x1=x; y1=y}) else (f2, F2 {y2=y}) ;; let use_closure (n:int) : int = let (code, env) = choose2 (true, 1, 2) in code (n, env) ;; use_closure 3;;