Require Import List.

  Ltac lrev l :=
    let rec loop aa ll :=
        match ll with
          | ?x::?ll => loop (x::aa) ll
          | nil => constr:(aa)
        end
    in match type of l with
         | list ?t => loop (@nil t) l
       end.

  Ltac lflat l :=
    let rec loop aa ll :=
        match ll with
          | ?ss++?rr => let bb := loop aa ss in
                        let cc := loop bb rr
                        in constr:(cc)
          | ?x::?rr => let bb := loop ((x::nil)::aa) rr
                        in constr:(bb)
          | nil => constr:(aa)
          | ?ss => constr:(ss::aa)
        end
    in match type of l with
         | list ?t => let r1 := loop (@nil (list t)) l
                      in lrev r1
       end.

  Ltac llin l :=
    let rec loop aa ll :=
        match ll with
          | (?x::nil)::?ll => let bb := loop (x::aa) ll
                              in constr:(bb)
          | ?lx::?ll => let bb := loop (lx++aa) ll
                              in constr:(bb)
          | nil => constr:(aa)
        end
    in match type of l with
         | list (list ?t) =>
         match lrev l with
          | ?lx::?rr => let bb := loop lx rr
                        in constr:(bb)
          | nil => constr:(@nil t)
         end
       end.

  Ltac lcut x l :=
    let rec loop aa x ll :=
        match ll with
           | x::_ => let bb := lrev aa
                          in constr:(bb++ll)
           | ?lz::?rr => let bb := loop (lz::aa) x rr
                          in constr:(bb)
        end
    in match type of l with
          | list (list ?t) => loop (@nil (list t)) x l
        end.

  Ltac lmerge l :=
    match l with
      | ?aa++?ll => let bb := llin aa in
                    let cc := llin ll
                    in constr:(bb++cc)
    end.

  Ltac focus_lst z r0 :=
    let r1 := lflat r0 in
    let r2 := lcut z r1 in
    let r3 := lmerge r2
    in constr:(r3).

  Ltac focus_lst_2 z r0 :=
    let r1 := focus_lst z r0 in
    let r2 := match r1 with
                | ?l++?x::?r =>
                let r3 := focus_lst z r in
                match r3 with
                  | ?m++?y::?n => constr:((l++x::m)++y::n)
                end
              end
    in constr:(r2).

  Ltac focus_lst_3 z r0 :=
    let r1 := focus_lst_2 z r0 in
    let r2 := match r1 with
                | ?l++?x::?r =>
                let r3 := focus_lst z r in
                match r3 with
                  | ?m++?y::?n => constr:((l++x::m)++y::n)
                end
              end
    in constr:(r2).

  Ltac focus_elt z l := focus_lst (z::nil) l.

Section test.

  Variable X : Type.

  Variable x y z : list X.
  Variable a b c : X.

  Goal True.
    let rr := lrev (1::2::3::4::nil) in idtac rr.
    let rr := lflat ((x++a::nil++nil)++b::z++y++a::nil) in idtac rr.
    let rr := llin (x::y::(a::nil)::z::(b::nil)::nil) in idtac rr.
    let rr := llin (@nil (list X)) in idtac rr.
    let rr := llin (@nil (list X)) in idtac rr.
    let rr := lcut z ( (x::y::(a::nil)::y::(b::nil)::z::nil) ) in idtac rr.
    let rr := lmerge ( (x::y::(a::nil)::nil)++(y::(b::nil)::z::nil) ) in idtac rr.
    let rr := focus_lst_2 (c::nil) ((x++c::nil++nil)++b::z++y++c::nil) in idtac rr.
    let rr := focus_lst_2 (c::nil) ((x++c::nil++nil)++b::z++y++c::z++c::x++c::z) in idtac rr.
    let rr := focus_lst z ((x++a::nil++nil)++b::z++y++c::nil) in idtac rr.
    let rr := focus_elt a (c::(x++a::nil++nil)++b::z++y++c::nil) in idtac rr.
    auto.
  Qed.

End test.