aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/monad.ml16
-rw-r--r--lib/monad.mli13
-rw-r--r--proofs/proofview.ml51
3 files changed, 34 insertions, 46 deletions
diff --git a/lib/monad.ml b/lib/monad.ml
index bc58c4d17..4a52684da 100644
--- a/lib/monad.ml
+++ b/lib/monad.ml
@@ -67,16 +67,11 @@ module type ListS = sig
(** {6 Two-list iterators} *)
- (** Raised when an combinator expects several lists of the same size
- but finds that they are not. Exceptions must be raised inside
- the monad, so two-list combinators take an extra argument to
- raise the exception. *)
- exception SizeMismatch
-
(** [fold_left2 r f s l1 l2] behaves like {!fold_left} but acts
- simultaneously on two lists. Returns [r SizeMismatch] if both lists
- do not have the same length. *)
- val fold_left2 : (exn->'a t) ->
+ simultaneously on two lists. Runs [r] (presumably an
+ exception-raising computation) if both lists do not have the
+ same length. *)
+ val fold_left2 : 'a t ->
('a -> 'b -> 'c -> 'a t) -> 'a -> 'b list -> 'c list -> 'a t
end
@@ -143,7 +138,6 @@ module Make (M:Def) : S with type +'a t = 'a M.t = struct
| a::b::l -> f a >> f b >> iter f l
- exception SizeMismatch
let rec fold_left2 r f x l1 l2 =
match l1,l2 with
@@ -153,7 +147,7 @@ module Make (M:Def) : S with type +'a t = 'a M.t = struct
f x a1 b1 >>= fun x' ->
f x' a2 b2 >>= fun x'' ->
fold_left2 r f x'' l1 l2
- | _ , _ -> r SizeMismatch
+ | _ , _ -> r
end
diff --git a/lib/monad.mli b/lib/monad.mli
index a6be1df7a..c8655efa0 100644
--- a/lib/monad.mli
+++ b/lib/monad.mli
@@ -69,16 +69,11 @@ module type ListS = sig
(** {6 Two-list iterators} *)
- (** Raised when an combinator expects several lists of the same size
- but finds that they are not. Exceptions must be raised inside
- the monad, so two-list combinators take an extra argument to
- raise the exception. *)
- exception SizeMismatch
-
(** [fold_left2 r f s l1 l2] behaves like {!fold_left} but acts
- simultaneously on two lists. Returns [r SizeMismatch] if both lists
- do not have the same length. *)
- val fold_left2 : (exn->'a t) ->
+ simultaneously on two lists. Runs [r] (presumably an
+ exception-raising computation) if both lists do not have the
+ same length. *)
+ val fold_left2 : 'a t ->
('a -> 'b -> 'c -> 'a t) -> 'a -> 'b list -> 'c list -> 'a t
end
diff --git a/proofs/proofview.ml b/proofs/proofview.ml
index a4ccdd687..569ae148a 100644
--- a/proofs/proofview.ml
+++ b/proofs/proofview.ml
@@ -374,10 +374,11 @@ let _ = Errors.register_handler begin function
| _ -> raise Errors.Unhandled
end
-(* A variant of [Monad.List.iter] where we iter over the focused list of
- goals. The argument tactic is executed in a focus comprising only
- of the current goal, a goal which has been solved by side effect is
- skipped. The generated subgoals are concatenated in order. *)
+(** A variant of [Monad.List.iter] where we iter over the focused list
+ of goals. The argument tactic is executed in a focus comprising
+ only of the current goal, a goal which has been solved by side
+ effect is skipped. The generated subgoals are concatenated in
+ order. *)
let iter_goal i =
let open Proof in
Comb.get >>= fun initial ->
@@ -392,31 +393,29 @@ let iter_goal i =
end [] initial >>= fun subgoals ->
Comb.set (CList.flatten (CList.rev subgoals))
-(* A variant of [Monad.List.fold_left2] where the first list is the
- list of focused goals. The argument tactic is executed in a focus
- comprising only of the current goal, a goal which has been solved
- by side effect is skipped. The generated subgoals are concatenated
- in order. *)
+(** A variant of [Monad.List.fold_left2] where the first list is the
+ list of focused goals. The argument tactic is executed in a focus
+ comprising only of the current goal, a goal which has been solved
+ by side effect is skipped. The generated subgoals are concatenated
+ in order. *)
let fold_left2_goal i s l =
let open Proof in
Pv.get >>= fun initial ->
- tclORELSE begin
- Proof.List.fold_left2 tclZERO begin fun ((r,subgoals) as cur) goal a ->
- Solution.get >>= fun step ->
- match advance step goal with
- | None -> return cur
- | Some goal ->
- Comb.set [goal] >>
- i goal a r >>= fun r ->
- Proof.map (fun comb -> (r, comb :: subgoals)) Comb.get
- end (s,[]) initial.comb l >>= fun (r,subgoals) ->
- Comb.set (CList.flatten (CList.rev subgoals)) >>
- return r
- end
- begin function
- | Proof.List.SizeMismatch -> tclZERO (SizeMismatch (CList.length initial.comb,CList.length l))
- | reraise -> tclZERO reraise
- end
+ let err =
+ return () >>= fun () -> (* Delay the computation of list lengths. *)
+ tclZERO (SizeMismatch (CList.length initial.comb,CList.length l))
+ in
+ Proof.List.fold_left2 err begin fun ((r,subgoals) as cur) goal a ->
+ Solution.get >>= fun step ->
+ match advance step goal with
+ | None -> return cur
+ | Some goal ->
+ Comb.set [goal] >>
+ i goal a r >>= fun r ->
+ Proof.map (fun comb -> (r, comb :: subgoals)) Comb.get
+ end (s,[]) initial.comb l >>= fun (r,subgoals) ->
+ Comb.set (CList.flatten (CList.rev subgoals)) >>
+ return r
(** Dispatch tacticals are used to apply a different tactic to each
goal under focus. They come in two flavours: [tclDISPATCH] takes a