anchor.diff:              try
                   match m.Entity.Value.MethodName with
                   | "Link" ->
  -                    match targ with
  -                    | ConcreteType ct ->
  -                        let mk = Id.New()
  -                        let action = Id.New()
  -                        let t = Reflection.loadType targ
  -                        let routeShape = getRouteShape t |> convertRouteShape
  -                        Let (mk, Call (None, routeMapBuilderT, makeLinkM, [routeShape]),
  -                            Lambda ([action],
  -                                Conditional (TypeCheck (Var action, targ),
  -                                    some (listOf stringT) (Application (Var mk, [Var action])),
  -                                    none (listOf stringT)
  -                                )
  +                    let mk = Id.New()
  +                    let action = Id.New()
  +                    let routeShape = getRouteShape targ |> convertRouteShape
  +                    Let (mk, Call (None, routeItemParsersT, makeLinkM, [routeShape]),
  +                        Lambda ([action],
  +                            Conditional (TypeCheck (Var action, targ),
  +                                some (listOf stringT) (Application (Var mk, [Var action])),
  +                                none (listOf stringT)
                               )
                           )
  -                    | _ -> failwith "Can only create a link for a concrete type"
  +                    )
                   | "Route" ->
  -                    let init, t = getDefaultCtor targ
  -                    let routeShape = getRouteShape t |> convertRouteShape
  -                    Call (None, routeMapBuilderT, parseRouteM, [routeShape; init])
  +                    let routeShape = getRouteShape targ |> convertRouteShape
  +                    Call (None, routeItemParsersT, parseRouteM, [routeShape])
                   | "Render" ->
                       let go = Id.New()
                       let action = Id.New()
  
positive.code:         let renders = renders |> List.rev |> List.map (fun f -> fun r -> f.Invoke(Action<obj>(Var.Set var), r))
          var.View.Doc(fun r -> List.pick ((|>) r) renders)
  
      static member private ParseShape(shape: RouteShape, init: unit -> obj) =
          fun (path: list<string>) ->
              let parseArgs (rest: list<string>) (args: Args) =
                  let v = init()
                  (Some rest, args)
                  ||> Seq.fold (fun rest (name, parse, _) ->
                      match rest with
                      | None -> None
                      | Some rest ->
                          match parse rest with
                          | None -> None
                          | Some (parsed, rest) ->
                              v?(name) <- parsed
                              Some rest
                  )
                  |> Option.map (fun rest -> (v, rest))
              match shape with
              | Root -> Some (init(), path)
              | Path (Some name, args) ->
                  match path with
                  | root :: rest when root = name -> parseArgs rest args
                  | _ -> None
              | Path (None, args) -> parseArgs path args
  
      static member private ParseRoute(shape, init) =
          RouteMapBuilder.ParseShape(shape, init) >> Option.bind (function
              | x, [] -> Some x
              | _ -> None
          )
  
      static member private MakeLink(shape: RouteShape) =
          fun (value: obj) ->
              match shape with
              | Root -> []
              | Path (name, args) ->
                  Option.toList name @
                  (args
                  |> Seq.collect (fun (name, _, link) -> link value?(name))
                  |> List.ofSeq)
  
  and private Args = array<string * (list<string> -> option<obj * list<string>>) * (obj -> list<string>)>
  
  and private RouteShape =
      | Root
      | Path of name: option<string> * args: Args
  
  and private MetaRootShape =
      | MetaRoot
      | MetaPath of name: option<string> * args: list<string * System.Type>
  
  and private RouteMapBuilderMacro(comp: Metadata.Compilation) =
      inherit Macro()
  
      let fsCoreType name = Hashed { Assembly = "FSharp.Core"; FullName = "Microsoft.FSharp." + name }
      let optionOf' t = concrete(fsCoreType "Core.FSharpOption`1", [t])
      let optionOf t = ConcreteType (optionOf' t)
      let some t v = NewUnionCase (optionOf' t, "Some", [v])
      let none t = NewUnionCase (optionOf' t, "None", [])
      let listOf' t = concrete(fsCoreType "Collections.FSharpList`1", [t])
      let listOf t = ConcreteType (listOf' t)
      let emptyList t = NewUnionCase (listOf' t, "Empty", [])
      let cons t hd tl = NewUnionCase (listOf' t, "Cons", [hd; tl])
      let stringT = concreteType(Hashed { Assembly = "mscorlib"; FullName = "System.String" }, [])
      let objT = concreteType(Hashed { Assembly = "mscorlib"; FullName = "System.Object" }, [])
      let routeMapBuilderT = concrete(Reflection.getTypeDefinition typeof<RouteMapBuilder>, [])
      let parseRouteM =
          concrete(
              typeof<RouteMapBuilder>.GetMethod("ParseRoute", BF.Static ||| BF.NonPublic)
              |> Reflection.getMethod
              |> Hashed,
              [])
      let parseShapeM =
          concrete(
              typeof<RouteMapBuilder>.GetMethod("ParseShape", BF.Static ||| BF.NonPublic)
              |> Reflection.getMethod
              |> Hashed,
              [])
      let makeLinkM =
          concrete(
              typeof<RouteMapBuilder>.GetMethod("MakeLink", BF.Static ||| BF.NonPublic)
              |> Reflection.getMethod
              |> Hashed,
              [])
      let parsersT = Reflection.getTypeDefinition typeof<RouteItemParsers>
  
      let getDefaultCtor (t: Type) =
          match t with
  
negative.code: 
  and [<JavaScript>] private RouteItemParsers =
  
      static member private ParseShape(shape: RouteShape) : ParseFunc =
          fun (path: list<string>) ->
              let parseArgs (init: unit -> obj) (rest: list<string>) (args: RouteObjectArgs) =
                  let v = init()
                  (Some rest, args)
                  ||> Seq.fold (fun rest (name, parse, _) ->
                      match rest with
                      | None -> None
                      | Some rest ->
                          match parse rest with
                          | None -> None
                          | Some (parsed, rest) ->
                              v?(name) <- parsed
                              Some rest
                  )
                  |> Option.map (fun rest -> (v, rest))
              match shape with
              | Base f -> f path
              | Object (init, Some name, args) ->
                  match path with
                  | root :: rest when root = name -> parseArgs init rest args
                  | _ -> None
              | Object (init, None, args) -> parseArgs init path args
              | Sequence (fromArray, parseItem, _) ->
                  RouteItemParsers.``System.Int32`` path
                  |> Option.bind (fun (length, rest) ->
                      let arr = Array.zeroCreate<obj> length
                      let rec set i rest =
                          if i = length then
                              Some (fromArray arr, rest)
                          else
                              match parseItem rest with
                              | None -> None
                              | Some (item, rest) ->
                                  arr.[i] <- item
                                  set (i + 1) rest
                      set 0 rest
                  )
  
      static member private ParseRoute(shape) =
          RouteItemParsers.ParseShape(shape) >> Option.bind (function
              | x, [] -> Some x
              | _ -> None
          )
  
      static member private MakeLink(shape: RouteShape) : LinkFunc =
          fun (value: obj) ->
              match shape with
              | Base _ -> [string value]
              | Object (_, name, args) ->
                  Option.toList name @
                  (args
                  |> Seq.collect (fun (name, _, link) -> link value?(name))
                  |> List.ofSeq)
              | Sequence (_, _, linkItem) ->
                  let s = value :?> seq<obj>
                  ([[string (Seq.length s)]], s)
                  ||> Seq.fold (fun a b -> linkItem b :: a)
                  |> List.rev
                  |> List.concat
  
      static member ``System.String``(x: list<string>) =
          match x with
          | [] -> None
  