anchor.diff:      let ExprArray (exprs: Expr<'T> seq) : Expr<'T[]> =
           Expr.NewArray(typeof<'T>, exprs |> Seq.cast |> List.ofSeq) |> Expr.Cast
   
  -type StringParts =
  -    | TextPart of string
  -    | TextHole of string
  +    type StringParts =
  +        | TextPart of string
  +        | TextHole of string
  +
  +    let ViewOf ty = typedefof<View<_>>.MakeGenericType([|ty|])
  +    let VarOf ty = typedefof<Var<_>>.MakeGenericType([|ty|])
  +
  +    [<RequireQualifiedAccess>]
  +    type Hole =
  +        | Var of valTy: System.Type * hasView: bool
  +        | View of valTy: System.Type
  +        | Simple of ty: System.Type
  +
  +        member this.ArgType =
  +            match this with
  +            | Var (valTy = t) -> VarOf t
  +            | View (valTy = t) -> ViewOf t
  +            | Simple (ty = t) -> t
   
   [<TypeProvider>]
   type TemplateProvider(cfg: TypeProviderConfig) as this =
  
positive.code:                                         let n = a.Name.LocalName
                                          if n.StartsWith dataEvent then
                                              let eventName = n.[dataEvent.Length..]
                                              let cbVar = getVar a.Value
                                              <@ Attr.Handler eventName %cbVar @>
                                          else
                                              match getParts a.Value with
                                              | [] -> <@ Attr.Create n "" @>
  
negative.code:                                     | null -> <@ Doc.Element n %attrs %nodes @>
                                      | a ->
                                          if n.ToLower() = "input" then
                                              <@ Doc.Input %attrs %(getVarHole a.Value) @>
                                          elif n.ToLower() = "textarea" then
                                              <@ Doc.InputArea %attrs %(getVarHole a.Value) @>
                                          else failwithf "data-var attribute \"%s\" on invalid element \"%s\"" a.Value n
  
                              | a -> getSimpleHole a.Value
                          
                          let mainExpr = t |> createNode true
  
                          let pars = [ for KeyValue(name, h) in holes -> ProvidedParameter(name, h.ArgType) ]
  
                          let code (args: Expr list) =
                              let varMap = Dictionary()
                              for KeyValue(name, hole), arg in Seq.zip holes args do
                                  match hole with
                                  | Hole.Simple ty ->
                                      varMap.Add((name, ty), arg)
                                  | Hole.View valTy ->
                                      varMap.Add((name, ViewOf valTy), arg)
                                  | Hole.Var(valTy, hasView) ->
                                      let varTy = VarOf valTy
                                      varMap.Add((name, varTy), arg)
                                      if hasView then
                                          varMap.Add((name, ViewOf valTy),
                                              Expr.Call(
                                                  typeof<View>.GetMethod("FromVar").MakeGenericMethod([|valTy|]),
                                                  [arg]))
                              mainExpr.Substitute(fun v ->
                                  match varMap.TryGetValue((v.Name, v.Type)) with
                                  | true, e -> Some e
                                  | false, _ -> None)
                          
                          ProvidedMethod("Doc", pars, typeof<Doc>, IsStaticMethod = true, InvokeCode = code)
                          |> toTy.AddMember
  