anchor.diff:              choice {
                   let! (sth, bod, pbod, lconsts, fvs) = v
                   let bvms = match_bvs tm pbod []
  -                let abod = deep_alpha bvms bod
  +                let! abod = deep_alpha bvms bod
                   let ath = EQ_MP (ALPHA bod abod) sth
                   let! tm1 = partfn abod
                   let! insts = term_match lconsts tm1 tm
  
positive.code:             }
              |> Choice.bindError (fun _ ->
                  let hop, args = strip_comb pat
                  let v = 
                      rev_assoc hop bcs
                      |> Option.toChoiceWithError "find"
                      |> Choice.bind (fun n ->
                          if length args = n
                          then BETAS_CONV n tm
                          else Choice.fail ())
                  v |> Choice.bindError (fun _ -> 
                      choice {
                          let! lpat, rpat = dest_comb pat
                          let! ltm, rtm = dest_comb tm
                          
                          let lth = HO_BETAS bcs lpat ltm
                          let v' = 
                              let rth = HO_BETAS bcs rpat rtm
                              MK_COMB(lth, rth)
                          return! v' |> Choice.bindError (fun _ -> AP_THM lth rtm)
                                     |> Choice.bindError (fun _ -> 
                                          let rth = HO_BETAS bcs rpat rtm
                                          AP_TERM ltm rth)
                      }))
  
      fun (bcs, tmin, tyin) th -> 
          let ith = 
              if tyin = [] then th
              else INST_TYPE tyin th
          if tmin = [] then ith
          else
              choice { 
                  let tth = INST tmin ith
                  let! tl1 = Choice.map hyp tth
                  let! tl2 = Choice.map hyp th
                  if tl1 = tl2 then 
                      if bcs = [] then 
                          return! tth
                      else 
                          let! itm = Choice.map concl ith
                          let! ttm = Choice.map concl tth
                          let v = 
                              let eth = HO_BETAS bcs itm ttm
                              EQ_MP eth tth
                          return! v |> Choice.bindError (fun _ -> tth)
                  else 
                      return! Choice.failwith "INSTANTIATE: term or type var free in assumptions"
              }
  
  /// Apply a higher-order instantiation to assumptions and conclusion of a theorem.
  let INSTANTIATE_ALL : instantiation -> thm -> thm = 
      let inst ((_, tmin, tyin) as i) th =
          if tmin = [] && tyin = [] then th
          else 
              let hyps = hyp <| Choice.get th
              if hyps = [] then INSTANTIATE i th
              else 
                  let tyrel, tyiirel = 
                      if tyin = [] then [], hyps
                      else 
                          let tvs = itlist (union << tyvars << snd) tyin []
                          partition (fun tm -> 
                                  let tvs' = Choice.get <| type_vars_in_term tm
                                  not(intersect tvs tvs' = [])) hyps
                  let tmrel, tmirrel = 
                      if tmin = [] then
                          [], tyiirel
                      else 
                          let vs = itlist (union << frees << snd) tmin []
                          partition (fun tm -> 
                                  let vs' = frees tm
                                  not(intersect vs vs' = [])) tyiirel
                  let rhyps = union tyrel tmrel
                  let th1 = rev_itlist DISCH rhyps th
                  let th2 = INSTANTIATE i th1
                  funpow (length rhyps) UNDISCH th2
      fun i th ->
          Choice.attemptNested <| fun () ->
              inst i th
  
  (* ------------------------------------------------------------------------- *)
  (* Higher order matching of terms.                                           *)
  
negative.code: 
  /// Apply a higher-order instantiation to a term.
  let instantiate : instantiation -> term -> Choice<term, exn> = 
      let betas n tm =
          choice {
          // CLEAN : Rename this value to something sensible.
          let! foo1 =
              ([], tm)
              |> Choice.funpow n (fun (l, t) ->
                  choice {
                  let! rand_t = rand t
                  let! rator_t = rator t
                  return rand_t :: l, rator_t
                  })
          
          return
              foo1
              // TODO : Modify this to use Choice.List.fold.
              ||> rev_itlist (fun a l ->
                  choice {
                  let! v, b = dest_abs l
                  return! vsubst [a, v] b
                  }
                  |> Choice.get)
          }
  
      let rec ho_betas bcs pat tm =
          if is_var pat || is_const pat then
              Choice.fail ()
          else
              choice {
              let! bv, bod = dest_abs tm
              let! body_pat = body pat
              // CLEAN : Rename this value to something sensible.
              let! foo1 = ho_betas bcs body_pat bod
              return! mk_abs(bv, foo1)
              }
              |> Choice.bindError (fun _ ->
                  let hop, args = strip_comb pat
                  match rev_assoc hop bcs with
                  | Some n when length args = n ->
                      betas n tm
                  | _ ->
                      // CLEAN : This should be reworked to simplify the code.
                      match dest_comb pat with
                      | Error error ->
                          Choice.error error
                      | Success (lpat, rpat) ->
                          match dest_comb tm with
                          | Error error ->
                              Choice.error error
                          | Success (ltm, rtm) ->
                              match ho_betas bcs lpat ltm with
                              | Success lth ->
                                  match ho_betas bcs rpat rtm with
                                  | Success rth ->
                                      mk_comb(lth, rth)
                                  | Error _ ->
                                      mk_comb(lth, rtm)
                              | Error _ ->
                                  match ho_betas bcs rpat rtm with
                                  | Success rth ->
                                      mk_comb(ltm, rth)
                                  | Error error ->
                                      Choice.error error)
  
      fun (bcs, tmin, tyin) tm ->
          choice {
          let! itm =
              choice {
              if List.isEmpty tyin then
                  return tm
              else
                  return! inst tyin tm }
  
          if List.isEmpty tmin then
              return itm
          else
              let! ttm = vsubst tmin itm
              if List.isEmpty bcs then
                  return ttm
              else
                  return!
                      ho_betas bcs itm ttm
                      |> Choice.bindError (fun _ ->
                          Choice.result ttm)
          }
  
  /// Apply a higher-order instantiation to conclusion of a theorem.
  let INSTANTIATE : instantiation -> thm -> thm = 
  