anchor.diff:    c
   
   (* private *)
  -
  -
  -let effect_args_from_repr (repr:term) (is_layered:bool) (r:Range.range) : list<term> =
  -  let err () =
  -    raise_error (Errors.Fatal_UnexpectedEffect,
  -      BU.format2 "Could not get effect args from repr %s with is_layered %s"
  -        (Print.term_to_string repr) (string_of_bool is_layered)) r in
  -  let repr = SS.compress repr in
  -  if is_layered
  -  then match repr.n with
  -       | Tm_app (_, _::is) -> is |> List.map fst
  -       | _ -> err ()
  -  else match repr.n with 
  -       | Tm_arrow (_, c) -> c |> U.comp_to_comp_typ |> (fun ct -> ct.effect_args |> List.map fst)
  -       | _ -> err ()
  -
   
   (*
    * Bind for indexed effects
  
positive.code:             if env.lax
              && Options.ml_ish() //NS: Disabling this optimization temporarily
              then S.tun
              else let a, kwp = Env.wp_signature env C.effect_PURE_lid in
                   let k = SS.subst [NT(a, t)] kwp in
                   let ret_wp = m |> U.get_return_vc_combinator in
                   N.normalize [Env.Beta; Env.NoFullNorm]
                              env
                              (mk_Tm_app (inst_effect_fun_with [u_t] env m ret_wp)
  
negative.code:   then C.effect_Tot_lid
    else join_effects env c1.eff_name c2.eff_name
  
  
  let lift_comps env c1 c2 (b:option<bv>) (for_bind:bool) : lident * comp * comp * guard_t =
    let c1 = Env.unfold_effect_abbrev env c1 in
    let c2 = Env.unfold_effect_abbrev env c2 in
    match Env.join_opt env c1.effect_name c2.effect_name with
    | Some (m, lift1, lift2) ->
      let c1, g1 = lift_comp env c1 lift1 in
      let c2, g2 =
        if not for_bind then lift_comp env c2 lift2
        else
          let x_a =
            match b with
            | None -> S.null_binder (U.comp_result c1)
            | Some x -> S.mk_binder x in
          let env_x = Env.push_binders env [x_a] in
          let c2, g2 = lift_comp env_x c2 lift2 in
          c2, Env.close_guard env [x_a] g2 in
      m, c1, c2, Env.conj_guard g1 g2
    | None ->
  
      (*
       * AR: we could not lift the comps using the wp lattice
       *     try using the polymonadic binds
       *     if there exists a polymonadic bind (M1, M2) |> M2,
       *       then lift using, lift_M1_M2 e = bind_M1_M2 e (fun x -> M2.return x)
       *
       *     (and similarly if exists (M2, M1) |> M1
       *
       *     we could also try to find a P such that (M1, P) |> P and (M2, P) |> P exist
       *       but leaving that for later
       *)
  
      let rng = env.range in
      let err () =
        raise_error (Errors.Fatal_EffectsCannotBeComposed,
          (BU.format2 "Effects %s and %s cannot be composed" 
            (Print.lid_to_string c1.effect_name) (Print.lid_to_string c2.effect_name))) rng in
  
      if Env.debug env <| Options.Other "LayeredEffects"
      then BU.print3 "Lifting comps %s and %s with for_bind %s{\n"
             (c1 |> S.mk_Comp |> Print.comp_to_string)
             (c2 |> S.mk_Comp |> Print.comp_to_string)
             (string_of_bool for_bind);
  
      if for_bind then err ()
      else
  
        let bind_with_return (ct:comp_typ) (ret_eff:lident) (f_bind:Env.polymonadic_bind_t)
        : comp * guard_t =
          let x_bv = S.gen_bv "x" None ct.result_typ in
          let c_ret, g_ret = mk_return
            (Env.push_bv env x_bv)
            (Env.get_effect_decl env ret_eff)
            (List.hd ct.comp_univs)
            ct.result_typ (S.bv_to_name x_bv) rng in
          let c, g_bind = f_bind env ct (Some x_bv) (U.comp_to_comp_typ c_ret) [] rng in
          c, Env.conj_guard g_ret g_bind in
  
        let try_lift c1 c2 : option<(lident * comp * comp * guard_t)> =
          let p_bind_opt = Env.exists_polymonadic_bind env c1.effect_name c2.effect_name in
          if p_bind_opt |> is_some
          then let Some (p, f_bind) = p_bind_opt in
               if lid_equals p c2.effect_name
               then (let c1, g = bind_with_return c1 p f_bind in
                     Some (c2.effect_name, c1, S.mk_Comp c2, g))
               else None
          else None in
    
        let p, c1, c2, g =
          match try_lift c1 c2 with
          | Some (p, c1, c2, g) -> p, c1, c2, g
          | None ->
            match try_lift c2 c1 with
            | Some (p, c2, c1, g) -> p, c1, c2, g
            | None -> err () in
  
        if Env.debug env <| Options.Other "LayeredEffects"
        then BU.print3 "} Returning p %s, c1 %s, and c2 %s\n"
               (Ident.string_of_lid p) (Print.comp_to_string c1) (Print.comp_to_string c2);
  
        p, c1, c2, g
  
  let is_pure_effect env l =
    let l = norm_eff_name env l in
  