anchor.diff:                          set = fun (ts : 't[]) (f : 'F) ->  ts.[i] <- inner.set ts.[i] f ; ts
                       }
               }
  +
  +        | Shape.FSharpList s, Item (:? int as i) :: rest ->
  +            s.Accept { new IFSharpListVisitor<Lens<'T,'F>> with
  +                member __.Visit<'t> () =
  +                    let inner = mkLensAux<'t, 'F> rest
  +                    wrap {
  +                        get = fun (ts : 't list) -> inner.get ts.[i]
  +                        set = fun (ts : 't list) (f : 'F) -> ts |> List.mapi (fun j t -> if j = i then inner.set t f else t)
  +                    }
  +            }
  +
  +        | Shape.FSharpMap s, Item key :: rest ->
  +            s.Accept { new IFSharpMapVisitor<Lens<'T, 'F>> with
  +                member __.Visit<'k, 'v when 'k : comparison>() =
  +                    let key = key :?> 'k
  +                    let inner = mkLensAux<'v, 'F> rest
  +                    wrap {
  +                        get = fun (ts : Map<'k,'v>) -> inner.get ts.[key]
  +                        set = fun (ts : Map<'k,'v>) f -> ts.Add(key, inner.set ts.[key] f)
  +                    }
  +            }
  +
  +        | Shape.Tuple (:? ShapeTuple<'T> as s), Item (:? int as i) :: rest ->
  +            s.Elements.[i] |> nest rest
   
           | Shape.FSharpRecord (:? ShapeFSharpRecord<'T> as s) & Shape.FSharpRef _, Property "Value" :: rest ->
               s.Fields |> Array.find (fun p -> p.Label = "contents") |> nest rest
  
positive.code:     type Path = Node list
      and Node =
          | Property of string
          | Item of int
  
      // converts a quotation of the form <@ fun x -> x.Foo.Bar.[0].Baz @> into a path
      let extractPath (e : Expr<'T -> 'F>) : Path =
          let rec aux v acc e =
              match e with
              | Var v' when v = v' -> acc
              | PropertyGet(Some o, p, [Value((:? int as i), _)]) when p.Name = "Item" -> aux v (Item i :: acc) o
              | PropertyGet(Some o, p, []) -> aux v (Property p.Name :: acc) o
              | Call(None, m, [o ; Value(:? int as i, _)]) when m.Name = "GetArray" && o.Type.IsArray && e.Type = o.Type.GetElementType() -> aux v (Item i :: acc) o
              // we support tuples, as they are often used to encode fields in erased type providers
  
negative.code:         | _ -> invalidArg "expr" "lens expressions must be lambda literals"
  
      let rec mkLensAux<'T, 'F> (path : Path) : Lens<'T, 'F> =
          let wrap (l : Lens<'a, 'F>) : Lens<'T, 'F> = unbox l
  
          let nest path (m : IShapeWriteMember<'T>) =
              m.Accept { new IWriteMemberVisitor<'T, Lens<'T, 'F>> with
                  member __.Visit<'F0> (m : ShapeWriteMember<'T, 'F0>) =
                      let inner = mkLensAux<'F0, 'F> path
                      {
                          get = fun (t:'T) -> inner.get (m.Project t)
                          set = fun (t:'T) (f:'F) -> m.Inject t (inner.set (m.Project t) f)
  