0
I Use This!
Inactive

News

Analyzed about 1 hour ago. based on code collected about 1 hour ago.
Posted almost 15 years ago by [email protected] (Mauricio Scheffer)
I've been blogging lately about functors in F#, in order to explain applicative functors, all so I could explain formlets now. Formlets are an abstraction of HTML forms. Formlets are composable, reusable, type-safe (as much as the host language is ... [More] type-safe anyway) and extensible. And they are described, of course, in terms of applicative functors.The concept of formlets was originally developed by Ezra Cooper, Sam Lindley, Philip Wadler, and Jeremy Yallop, as part of their research for Links, a new programming language oriented to web applications.Since its introduction in 2008, formlets proved to be a very popular concept, being ported to Haskell, Scheme (Racket), Common Lisp (Hunchentoot), Scala and JavaScript. If you regularly read the news about F# you probably know about WebSharper, a cool web framework for F#, which has formlets as one of its many features. Being a commercial product, WebSharper has great documentation on how to use formlets, but they only briefly mention the underlying concepts on how they work.Let's see a sample formlet in an ASP.NET MVC application:open System open System.Web open System.Web.Mvc open System.Collections.Generic [<HandleError>] type HomeController() = inherit Controller() let inputInt = lift int input let inputDate = puree (fun month day year -> DateTime(year,month,day)) <*> text "Month: " *> inputInt <*> text "Day: " *> inputInt <*> text "Year: " *> inputInt let formlet = puree (fun name order ship amount -> name,order,ship,amount) <*> text "Name: " *> input <* br <*> text "Order date: " *> inputDate <* br <*> text "Shipping date: " *> inputDate <* br <*> text "Qty: " *> inputInt <* br member x.Index() = x.ViewData.["Message"] <- "Welcome to ASP.NET MVC!" x.View(box <| render formlet) :> ActionResult member x.Register() = let env = fromNV x.Request.Form let name,orderDate,shippingDate,amount = run formlet env x.ViewData.["Name"] <- name x.ViewData.["Ordered"] <- orderDate x.ViewData.["Shipping"] <- shippingDate x.ViewData.["Amount"] <- amount x.View() :> ActionResult F# Web SnippetsIndex.aspx:<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Home Page asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2><%: ViewData["Message"] %>h2> <p> <% using (Html.BeginForm("Register", "Home")) { %> <%= Model%> <input type="submit" value="Submit" /> <% } %> p> asp:Content> Register.aspx<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Register asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <%: ViewData["Ordered"] %>: <%: ViewData["Name"] %> has requested <%: ViewData["Amount"] %> items to be delivered on <%: ViewData["Shipping"] %> asp:Content> You can hover over any value on the F# snippets in this post and get a tooltip with types, thanks to F# Web Snippets.If you read my previous articles on applicative functors you'll recognize the standard operations pure (or puree), <*> and lift. Note how the final formlet is composed from more basic formlets: one that models date input, which in turn uses an formlet to input integers. They all rely on a primitive input formlet (of type string Formlet) that models an . Also note that we didn't define the name attribute for any input; formlets generate them automatically and also match them when handling submitted values. Running the app shows a form like this:First thing that should spring to your mind when seeing this is "boy, this is ugly", otherwise I'm not doing my job right :) Let's see now, step by step, how formlets can be implemented. We start by defining the types. First, a simple model of XML to represent HTML:type xml_item = | Text of string | Tag of string * (string*string) list * xml_item list // name * attributes * childrenWe define an environment that will hold key-value pairs from submitted forms:type Env = (string*string) listAnd finally, the Formlet type:type 'a Formlet = int -> (xml_item list * (Env -> 'a) * int)Type signatures carry a lot of information, so let's take a moment to read this. It's a function that takes an int and returns a tuple of stuff. We'll see that the int it takes is used to generate the form element name. The tuple of stuff returned contains: an XML forest (representing HTML), a function we'll call collector, and an int that will be used to generate the next form element name. The collector is used to lookup the submitted value from the environment.A formlet is an applicative functor, so let's define puree:[<AutoOpen>] module Formlet = let puree (v: 'a) : 'a Formlet = fun i -> [], (fun _ -> v), iIt's an empty XML, a constant collector, and the same input i. Here's the definition of <*> :let (<*>) (f: ('a -> 'b) Formlet) (a: 'a Formlet) : 'b Formlet = fun i -> let x1,g,i = f i let x2,q,i = a i x1 @ x2, (fun env -> g env (q env)), iStep by step: we apply f, since it holds an 'a -> 'b, the collector g collects a function 'a -> 'b. Then we apply a. We return the concatenation of XML forests, the composition of collectors, and the final name seed.Now some standard functions for applicative functors:let lift f a = puree f <*> a let lift2 f a b : _ Formlet = puree f <*> a <*> b let ( *>) f a : _ Formlet = lift2 (fun _ z -> z) f a let ( <*) f a : _ Formlet = lift2 (fun z _ -> z) f aA couple of functions to lift pure markup and text:let xml (x: xml_item list) : unit Formlet = fun i -> x, (fun _ -> ()), i let text (t: string) : unit Formlet = xml [Text t]The tag function creates a tag that wraps a formlet:let tag (name: string) (attr: (string*string) list) (f: 'a Formlet) : 'a Formlet = fun i -> let xml,env,i = f i [Tag(name, attr, xml)],env,inextName is responsible for generating form element names:let nextName = fun i -> "input_" + i.ToString(), i+1Note that it returns an incremented counter, to be used in the following name. The input primitive:let input : string Formlet = fun i -> let name,i = nextName i let collector = List.find (fun (k,_) -> k = name) >> snd let tag = Tag("input", ["name",name], []) [tag], collector, iThe input formlet shows how everything fits together. It generates a fresh name to be used both in the collector and the input tag. This is what keeps the rendered form element and its respective collected value in sync.Here's a simple for formatting:let br: unit Formlet = xml [Tag("br",[],[])]The run function gets the collector of a formlet, which in turn will produce the collected value when applied to the environment: let run (f: 'a Formlet) : Env -> 'a = let _,e,_ = f 0 eThat zero is the seed for form element names. We render a formlet by mapping it to a System.Xml.Linq.XDocument: open System.Xml.Linq let render (f: 'a Formlet) : XDocument = let xml,_,_ = f 0 let (!!) t = XName.op_Implicit t let xtext (s: string) = XText s :> XObject let xattr (name, value) = XAttribute(!!name, value) :> XObject let xattrs attr = List.map xattr attr let xelem name attr children = XElement(!!name, attr @ children) :> XObject let rec renderForest x = let render' = function | Text t -> xtext t | Tag(name, attr, children) -> xelem name (xattrs attr) (renderForest children) List.map render' x let root = xelem "div" [] (renderForest xml) XDocument rootA helper function to make an Env from a NameValueCollection (such as Request.Form):open System.Collections.Specialized let fromNV (a: NameValueCollection) = a.AllKeys |> Seq.collect (fun k -> a.GetValues k |> Seq.map (fun v -> k,v)) |> Seq.toListEven though this was a bare bones implementation of formlets, I hope it served to illustrate how they work. This implementation was taken almost verbatim from the paper The Essence of Form Abstraction [PDF] by the original developers of Formlets mentioned at the beginning of this article. I kept it as simple and clear as possible, with many type annotations that weren't really necessary and intentionally cutting out features.Full source code is here.Next, we'll see how formlets can be factored to a composition of primitive applicatives.Read this article in Serbo-Croatian (translated by Anja Skrba from Webhostinggeeks.com) namespace Formlets union case xml_item.Text: string -> xml_item Multiple items val string : 'T -> string Full name: Microsoft.FSharp.Core.Operators.string -------------------- type string = System.String Full name: Microsoft.FSharp.Core.string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable union case xml_item.Tag: string * (string * string) list * xml_item list -> xml_item type 'T list = List<'T> Full name: Microsoft.FSharp.Collections.list<_>   type: 'T list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'T>   implements: System.Collections.IEnumerable type xml_item =   | Text of string   | Tag of string * (string * string) list * xml_item list Full name: Formlets.xml_item   type: xml_item   implements: System.IEquatable   implements: System.Collections.IStructuralEquatable   implements: System.IComparable   implements: System.IComparable   implements: System.Collections.IStructuralComparable type Env = (string * string) list Full name: Formlets.Env   type: Env   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable type 'a Formlet = int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet<_> Multiple items val int : 'T -> int (requires member op_Explicit) Full name: Microsoft.FSharp.Core.Operators.int -------------------- type int<'Measure> = int Full name: Microsoft.FSharp.Core.int<_>   type: int<'Measure>   implements: System.IComparable   implements: System.IConvertible   implements: System.IFormattable   implements: System.IComparable>   implements: System.IEquatable>   inherits: System.ValueType -------------------- type int = int32 Full name: Microsoft.FSharp.Core.int   type: int   implements: System.IComparable   implements: System.IFormattable   implements: System.IConvertible   implements: System.IComparable   implements: System.IEquatable   inherits: System.ValueType type AutoOpenAttribute =   class     inherit System.Attribute     new : unit -> AutoOpenAttribute     new : path:string -> AutoOpenAttribute     member Path : string   end Full name: Microsoft.FSharp.Core.AutoOpenAttribute   type: AutoOpenAttribute   implements: System.Runtime.InteropServices._Attribute   inherits: System.Attribute val puree : 'a -> int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet.puree val v : 'a val i : int   type: int   implements: System.IComparable   implements: System.IFormattable   implements: System.IConvertible   implements: System.IComparable   implements: System.IEquatable   inherits: System.ValueType val f : ('a -> 'b) Formlet val a : 'a Formlet val x1 : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val g : (Env -> 'a -> 'b) val x2 : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val q : (Env -> 'a) val env : Env   type: Env   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val lift : ('a -> 'b) -> 'a Formlet -> 'b Formlet Full name: Formlets.Formlet.lift val f : ('a -> 'b) val lift2 : ('a -> 'b -> 'c) -> 'a Formlet -> 'b Formlet -> 'c Formlet Full name: Formlets.Formlet.lift2 val f : ('a -> 'b -> 'c) val b : 'b Formlet val f : 'a Formlet val a : 'b Formlet val z : 'b val z : 'a val xml : xml_item list -> int -> xml_item list * (Env -> unit) * int Full name: Formlets.Formlet.xml val x : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable type unit = Unit Full name: Microsoft.FSharp.Core.unit   type: unit   implements: System.IComparable val text : string -> unit Formlet Full name: Formlets.Formlet.text val t : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable val tag : string -> (string * string) list -> 'a Formlet -> int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet.tag val name : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable val attr : (string * string) list   type: (string * string) list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val xml : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val env : (Env -> 'a) val nextName : int -> string * int Full name: Formlets.Formlet.nextName Multiple overloads System.Object.ToString() : string System.Int32.ToString(provider: System.IFormatProvider) : string System.Int32.ToString(format: string) : string System.Int32.ToString(format: string, provider: System.IFormatProvider) : string val input : int -> xml_item list * (Env -> string) * int Full name: Formlets.Formlet.input val lookup : ((string * string) list -> string) Multiple items module List from Microsoft.FSharp.Collections -------------------- type List<'T> =   | ( [] )   | ( :: ) of 'T * 'T list   with     interface System.Collections.IEnumerable     interface System.Collections.Generic.IEnumerable<'T>     member Head : 'T     member IsEmpty : bool     member Item : index:int -> 'T with get     member Length : int     member Tail : 'T list     static member Cons : head:'T * tail:'T list -> 'T list     static member Empty : 'T list   end Full name: Microsoft.FSharp.Collections.List<_>   type: List<'T>   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'T>   implements: System.Collections.IEnumerable val find : ('T -> bool) -> 'T list -> 'T Full name: Microsoft.FSharp.Collections.List.find val k : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable val snd : ('T1 * 'T2) -> 'T2 Full name: Microsoft.FSharp.Core.Operators.snd val tag : xml_item   type: xml_item   implements: System.IEquatable   implements: System.Collections.IStructuralEquatable   implements: System.IComparable   implements: System.IComparable   implements: System.Collections.IStructuralComparable val br : unit Formlet Full name: Formlets.Formlet.br val run : 'a Formlet -> (Env -> 'a) Full name: Formlets.Formlet.run val e : (Env -> 'a) namespace System namespace System.Xml namespace System.Xml.Linq val render : 'a Formlet -> XDocument Full name: Formlets.Formlet.render type XDocument =   class     inherit System.Xml.Linq.XContainer     new : unit -> System.Xml.Linq.XDocument     new : obj [] -> System.Xml.Linq.XDocument     new : System.Xml.Linq.XDeclaration * obj [] -> System.Xml.Linq.XDocument     new : System.Xml.Linq.XDocument -> System.Xml.Linq.XDocument     member Declaration : System.Xml.Linq.XDeclaration with get, set     member DocumentType : System.Xml.Linq.XDocumentType     member NodeType : System.Xml.XmlNodeType     member Root : System.Xml.Linq.XElement     member Save : string -> unit     member Save : System.IO.TextWriter -> unit     member Save : System.Xml.XmlWriter -> unit     member Save : string * System.Xml.Linq.SaveOptions -> unit     member Save : System.IO.TextWriter * System.Xml.Linq.SaveOptions -> unit     member WriteTo : System.Xml.XmlWriter -> unit     static member Load : string -> System.Xml.Linq.XDocument     static member Load : System.IO.TextReader -> System.Xml.Linq.XDocument     static member Load : System.Xml.XmlReader -> System.Xml.Linq.XDocument     static member Load : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Load : System.IO.TextReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Load : System.Xml.XmlReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Parse : string -> System.Xml.Linq.XDocument     static member Parse : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument   end Full name: System.Xml.Linq.XDocument   type: XDocument   implements: System.Xml.IXmlLineInfo   inherits: XContainer   inherits: XNode   inherits: XObject type XName =   class     member Equals : obj -> bool     member GetHashCode : unit -> int     member LocalName : string     member Namespace : System.Xml.Linq.XNamespace     member NamespaceName : string     member ToString : unit -> string     static member Get : string -> System.Xml.Linq.XName     static member Get : string * string -> System.Xml.Linq.XName   end Full name: System.Xml.Linq.XName   type: XName   implements: System.IEquatable   implements: System.Runtime.Serialization.ISerializable XName.op_Implicit(expandedName: string) : XName val xtext : (string -> XObject) val s : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable type XText =   class     inherit System.Xml.Linq.XNode     new : string -> System.Xml.Linq.XText     new : System.Xml.Linq.XText -> System.Xml.Linq.XText     member NodeType : System.Xml.XmlNodeType     member Value : string with get, set     member WriteTo : System.Xml.XmlWriter -> unit   end Full name: System.Xml.Linq.XText   type: XText   implements: System.Xml.IXmlLineInfo   inherits: XNode   inherits: XObject type XObject =   class     member AddAnnotation : obj -> unit     member Annotation<'T> : unit -> 'T     member Annotation : System.Type -> obj     member Annotations<'T> : unit -> System.Collections.Generic.IEnumerable<'T>     member Annotations : System.Type -> System.Collections.Generic.IEnumerable     member BaseUri : string     member Document : System.Xml.Linq.XDocument     member NodeType : System.Xml.XmlNodeType     member Parent : System.Xml.Linq.XElement     member RemoveAnnotations<'T> : unit -> unit     member RemoveAnnotations : System.Type -> unit   end Full name: System.Xml.Linq.XObject   type: XObject   implements: System.Xml.IXmlLineInfo val xattr : (string * 'b -> XObject) val value : 'b type XAttribute =   class     inherit System.Xml.Linq.XObject     new : System.Xml.Linq.XName * obj -> System.Xml.Linq.XAttribute     new : System.Xml.Linq.XAttribute -> System.Xml.Linq.XAttribute     member IsNamespaceDeclaration : bool     member Name : System.Xml.Linq.XName     member NextAttribute : System.Xml.Linq.XAttribute     member NodeType : System.Xml.XmlNodeType     member PreviousAttribute : System.Xml.Linq.XAttribute     member Remove : unit -> unit     member SetValue : obj -> unit     member ToString : unit -> string     member Value : string with get, set     static member EmptySequence : System.Collections.Generic.IEnumerable   end Full name: System.Xml.Linq.XAttribute   type: XAttribute   implements: System.Xml.IXmlLineInfo   inherits: XObject val xattrs : ((string * 'b) list -> XObject list) val attr : (string * 'b) list   type: (string * 'b) list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val map : ('T -> 'U) -> 'T list -> 'U list Full name: Microsoft.FSharp.Collections.List.map val xelem : (string -> 'b list -> 'b list -> XObject) val attr : 'b list   type: 'b list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'b>   implements: System.Collections.IEnumerable val children : 'b list   type: 'b list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'b>   implements: System.Collections.IEnumerable type XElement =   class     inherit System.Xml.Linq.XContainer     new : System.Xml.Linq.XName -> System.Xml.Linq.XElement     new : System.Xml.Linq.XName * obj -> System.Xml.Linq.XElement     new : System.Xml.Linq.XName * obj [] -> System.Xml.Linq.XElement     new : System.Xml.Linq.XElement -> System.Xml.Linq.XElement     new : System.Xml.Linq.XStreamingElement -> System.Xml.Linq.XElement     member AncestorsAndSelf : unit -> System.Collections.Generic.IEnumerable     member AncestorsAndSelf : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable     member Attribute : System.Xml.Linq.XName -> System.Xml.Linq.XAttribute     member Attributes : unit -> System.Collections.Generic.IEnumerable     member Attributes : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable     member DescendantNodesAndSelf : unit -> System.Collections.Generic.IEnumerable     member DescendantsAndSelf : unit -> System.Collections.Generic.IEnumerable     member DescendantsAndSelf : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable     member FirstAttribute : System.Xml.Linq.XAttribute     member GetDefaultNamespace : unit -> System.Xml.Linq.XNamespace     member GetNamespaceOfPrefix : string -> System.Xml.Linq.XNamespace     member GetPrefixOfNamespace : System.Xml.Linq.XNamespace -> string     member HasAttributes : bool     member HasElements : bool     member IsEmpty : bool     member LastAttribute : System.Xml.Linq.XAttribute     member Name : System.Xml.Linq.XName with get, set     member NodeType : System.Xml.XmlNodeType     member RemoveAll : unit -> unit     member RemoveAttributes : unit -> unit     member ReplaceAll : obj -> unit     member ReplaceAll : obj [] -> unit     member ReplaceAttributes : obj -> unit     member ReplaceAttributes : obj [] -> unit     member Save : string -> unit     member Save : System.IO.TextWriter -> unit     member Save : System.Xml.XmlWriter -> unit     member Save : string * System.Xml.Linq.SaveOptions -> unit     member Save : System.IO.TextWriter * System.Xml.Linq.SaveOptions -> unit     member SetAttributeValue : System.Xml.Linq.XName * obj -> unit     member SetElementValue : System.Xml.Linq.XName * obj -> unit     member SetValue : obj -> unit     member Value : string with get, set     member WriteTo : System.Xml.XmlWriter -> unit     static member EmptySequence : System.Collections.Generic.IEnumerable     static member Load : string -> System.Xml.Linq.XElement     static member Load : System.IO.TextReader -> System.Xml.Linq.XElement     static member Load : System.Xml.XmlReader -> System.Xml.Linq.XElement     static member Load : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Load : System.IO.TextReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Load : System.Xml.XmlReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Parse : string -> System.Xml.Linq.XElement     static member Parse : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement   end Full name: System.Xml.Linq.XElement   type: XElement   implements: System.Xml.IXmlLineInfo   implements: System.Xml.Serialization.IXmlSerializable   inherits: XContainer   inherits: XNode   inherits: XObject val renderForest : (xml_item list -> XObject list) val render' : (xml_item -> XObject) val children : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable   implements: System.Collections.IEnumerable val root : XObject   type: XObject   implements: System.Xml.IXmlLineInfo namespace System.Collections namespace System.Collections.Specialized val fromNV : NameValueCollection -> (string * string) list Full name: Formlets.Formlet.fromNV val a : NameValueCollection   type: NameValueCollection   implements: System.Collections.ICollection   implements: System.Collections.IEnumerable   implements: System.Runtime.Serialization.ISerializable   implements: System.Runtime.Serialization.IDeserializationCallback   inherits: NameObjectCollectionBase type NameValueCollection =   class     inherit System.Collections.Specialized.NameObjectCollectionBase     new : unit -> System.Collections.Specialized.NameValueCollection     new : System.Collections.Specialized.NameValueCollection -> System.Collections.Specialized.NameValueCollection     new : System.Collections.IHashCodeProvider * System.Collections.IComparer -> System.Collections.Specialized.NameValueCollection     new : int -> System.Collections.Specialized.NameValueCollection     new : System.Collections.IEqualityComparer -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.IEqualityComparer -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.Specialized.NameValueCollection -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.IHashCodeProvider * System.Collections.IComparer -> System.Collections.Specialized.NameValueCollection     member Add : System.Collections.Specialized.NameValueCollection -> unit     member Add : string * string -> unit     member AllKeys : string []     member Clear : unit -> unit     member CopyTo : System.Array * int -> unit     member Get : string -> string     member Get : int -> string     member GetKey : int -> string     member GetValues : string -> string []     member GetValues : int -> string []     member HasKeys : unit -> bool     member Item : string -> string with get, set     member Item : int -> string     member Remove : string -> unit     member Set : string * string -> unit   end Full name: System.Collections.Specialized.NameValueCollection   type: NameValueCollection   implements: System.Collections.ICollection   implements: System.Collections.IEnumerable   implements: System.Runtime.Serialization.ISerializable   implements: System.Runtime.Serialization.IDeserializationCallback   inherits: NameObjectCollectionBase property NameValueCollection.AllKeys: string [] module Seq from Microsoft.FSharp.Collections val collect : ('T -> #seq<'U>) -> seq<'T> -> seq<'U> Full name: Microsoft.FSharp.Collections.Seq.collect Multiple overloads NameValueCollection.GetValues(index: int) : string [] NameValueCollection.GetValues(name: string) : string [] val map : ('T -> 'U) -> seq<'T> -> seq<'U> Full name: Microsoft.FSharp.Collections.Seq.map val v : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable   implements: seq   implements: System.Collections.IEnumerable   implements: System.IEquatable val toList : seq<'T> -> 'T list Full name: Microsoft.FSharp.Collections.Seq.toList namespace System.Web namespace System.Web.Mvc namespace System.Collections.Generic type HandleErrorAttribute =   class     inherit System.Web.Mvc.FilterAttribute     new : unit -> System.Web.Mvc.HandleErrorAttribute     member ExceptionType : System.Type with get, set     member Master : string with get, set     member OnException : System.Web.Mvc.ExceptionContext -> unit     member View : string with get, set   end Full name: System.Web.Mvc.HandleErrorAttribute   type: HandleErrorAttribute   implements: Runtime.InteropServices._Attribute   implements: IExceptionFilter   inherits: FilterAttribute   inherits: Attribute type HomeController =   class     inherit Controller     new : unit -> HomeController     member Index : unit -> ActionResult     member Register : unit -> ActionResult   end Full name: Formlets.HomeController   type: HomeController   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: Controller   inherits: ControllerBase   inherits: MarshalByRefObject type Controller =   class     inherit System.Web.Mvc.ControllerBase     member ActionInvoker : System.Web.Mvc.IActionInvoker with get, set     member Dispose : unit -> unit     member HttpContext : System.Web.HttpContextBase     member ModelState : System.Web.Mvc.ModelStateDictionary     member Request : System.Web.HttpRequestBase     member Response : System.Web.HttpResponseBase     member RouteData : System.Web.Routing.RouteData     member Server : System.Web.HttpServerUtilityBase     member Session : System.Web.HttpSessionStateBase     member TempDataProvider : System.Web.Mvc.ITempDataProvider with get, set     member Url : System.Web.Mvc.UrlHelper with get, set     member User : System.Security.Principal.IPrincipal   end Full name: System.Web.Mvc.Controller   type: Controller   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: ControllerBase   inherits: MarshalByRefObject val inputInt : int Formlet Multiple items val int : 'T -> int (requires member op_Explicit) Full name: Microsoft.FSharp.Core.Operators.int -------------------- type int<'Measure> = int Full name: Microsoft.FSharp.Core.int<_>   type: int<'Measure>   implements: IComparable   implements: IConvertible   implements: IFormattable   implements: IComparable>   implements: IEquatable>   inherits: ValueType -------------------- type int = int32 Full name: Microsoft.FSharp.Core.int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable   implements: IEquatable   inherits: ValueType val inputDate : DateTime Formlet val month : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable   implements: IEquatable   inherits: ValueType val day : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable   implements: IEquatable   inherits: ValueType val year : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable   implements: IEquatable   inherits: ValueType type DateTime =   struct     new : int64 -> System.DateTime     new : int64 * System.DateTimeKind -> System.DateTime     new : int * int * int -> System.DateTime     new : int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int -> System.DateTime     new : int * int * int * int * int * int * System.DateTimeKind -> System.DateTime     new : int * int * int * int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int * int -> System.DateTime     new : int * int * int * int * int * int * int * System.DateTimeKind -> System.DateTime     new : int * int * int * int * int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int * int * System.Globalization.Calendar * System.DateTimeKind -> System.DateTime     member Add : System.TimeSpan -> System.DateTime     member AddDays : float -> System.DateTime     member AddHours : float -> System.DateTime     member AddMilliseconds : float -> System.DateTime     member AddMinutes : float -> System.DateTime     member AddMonths : int -> System.DateTime     member AddSeconds : float -> System.DateTime     member AddTicks : int64 -> System.DateTime     member AddYears : int -> System.DateTime     member CompareTo : obj -> int     member CompareTo : System.DateTime -> int     member Date : System.DateTime     member Day : int     member DayOfWeek : System.DayOfWeek     member DayOfYear : int     member Equals : obj -> bool     member Equals : System.DateTime -> bool     member GetDateTimeFormats : unit -> string []     member GetDateTimeFormats : System.IFormatProvider -> string []     member GetDateTimeFormats : char -> string []     member GetDateTimeFormats : char * System.IFormatProvider -> string []     member GetHashCode : unit -> int     member GetTypeCode : unit -> System.TypeCode     member Hour : int     member IsDaylightSavingTime : unit -> bool     member Kind : System.DateTimeKind     member Millisecond : int     member Minute : int     member Month : int     member Second : int     member Subtract : System.DateTime -> System.TimeSpan     member Subtract : System.TimeSpan -> System.DateTime     member Ticks : int64     member TimeOfDay : System.TimeSpan     member ToBinary : unit -> int64     member ToFileTime : unit -> int64     member ToFileTimeUtc : unit -> int64     member ToLocalTime : unit -> System.DateTime     member ToLongDateString : unit -> string     member ToLongTimeString : unit -> string     member ToOADate : unit -> float     member ToShortDateString : unit -> string     member ToShortTimeString : unit -> string     member ToString : unit -> string     member ToString : string -> string     member ToString : System.IFormatProvider -> string     member ToString : string * System.IFormatProvider -> string     member ToUniversalTime : unit -> System.DateTime     member Year : int     static val MinValue : System.DateTime     static val MaxValue : System.DateTime     static member Compare : System.DateTime * System.DateTime -> int     static member DaysInMonth : int * int -> int     static member Equals : System.DateTime * System.DateTime -> bool     static member FromBinary : int64 -> System.DateTime     static member FromFileTime : int64 -> System.DateTime     static member FromFileTimeUtc : int64 -> System.DateTime     static member FromOADate : float -> System.DateTime     static member IsLeapYear : int -> bool     static member Now : System.DateTime     static member Parse : string -> System.DateTime     static member Parse : string * System.IFormatProvider -> System.DateTime     static member Parse : string * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member ParseExact : string * string * System.IFormatProvider -> System.DateTime     static member ParseExact : string * string * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member ParseExact : string * string [] * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member SpecifyKind : System.DateTime * System.DateTimeKind -> System.DateTime     static member Today : System.DateTime     static member TryParse : string * System.DateTime -> bool     static member TryParse : string * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member TryParseExact : string * string * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member TryParseExact : string * string [] * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member UtcNow : System.DateTime   end Full name: System.DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable   implements: IEquatable   inherits: ValueType val formlet : (string * DateTime * DateTime * int) Formlet val name : string   type: string   implements: IComparable   implements: ICloneable   implements: IConvertible   implements: IComparable   implements: seq   implements: Collections.IEnumerable   implements: IEquatable val order : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable   implements: IEquatable   inherits: ValueType val ship : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable   implements: IEquatable   inherits: ValueType val amount : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable   implements: IEquatable   inherits: ValueType val x : HomeController   type: HomeController   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: Controller   inherits: ControllerBase   inherits: MarshalByRefObject member HomeController.Index : unit -> ActionResult Full name: Formlets.HomeController.Index property ControllerBase.ViewData: ViewDataDictionary Multiple overloads Controller.View() : ViewResult Controller.View(view: IView) : ViewResult Controller.View(viewName: string) : ViewResult Controller.View(model: obj) : ViewResult Controller.View(view: IView, model: obj) : ViewResult Controller.View(viewName: string, model: obj) : ViewResult Controller.View(viewName: string, masterName: string) : ViewResult Controller.View(viewName: string, masterName: string, model: obj) : ViewResult val box : 'T -> obj Full name: Microsoft.FSharp.Core.Operators.box val render : 'a Formlet -> Xml.Linq.XDocument Full name: Formlets.Formlet.render type ActionResult =   class     member ExecuteResult : System.Web.Mvc.ControllerContext -> unit   end Full name: System.Web.Mvc.ActionResult member HomeController.Register : unit -> ActionResult Full name: Formlets.HomeController.Register val env : (string * string) list   type: (string * string) list   implements: Collections.IStructuralEquatable   implements: IComparable>   implements: IComparable   implements: Collections.IStructuralComparable   implements: IEnumerable   implements: Collections.IEnumerable val fromNV : Collections.Specialized.NameValueCollection -> (string * string) list Full name: Formlets.Formlet.fromNV property Controller.Request: HttpRequestBase property HttpRequestBase.Form: Collections.Specialized.NameValueCollection val orderDate : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable   implements: IEquatable   inherits: ValueType val shippingDate : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable   implements: IEquatable   inherits: ValueType [Less]
Posted almost 15 years ago by [email protected] (mausch)
I've been blogging lately about functors in F#, in order to explain applicative functors, all so I could explain formlets now. Formlets are an abstraction of HTML forms. Formlets are composable, reusable, type-safe (as much as the host language is ... [More] type-safe anyway) and extensible. And they are described, of course, in terms of applicative functors. The concept of formlets was originally developed by Ezra Cooper, Sam Lindley, Philip Wadler, and Jeremy Yallop, as part of their research for Links, a new programming language oriented to web applications. Since its introduction in 2008, formlets proved to be a very popular concept, being ported to Haskell, Scheme (Racket), Common Lisp (Hunchentoot), Scala and JavaScript. If you regularly read the news about F# you probably know about WebSharper, a cool web framework for F#, which has formlets as one of its many features. Being a commercial product, WebSharper has great documentation on how to use formlets, but they only briefly mention the underlying concepts on how they work. Let's see a sample formlet in an ASP.NET MVC application: open System open System.Web open System.Web.Mvc open System.Collections.Generic [<HandleError>] type HomeController() = inherit Controller() let inputInt = lift int input let inputDate = puree (fun month day year -> DateTime(year,month,day)) <*> text "Month: " *> inputInt <*> text "Day: " *> inputInt <*> text "Year: " *> inputInt let formlet = puree (fun name order ship amount -> name,order,ship,amount) <*> text "Name: " *> input <* br <*> text "Order date: " *> inputDate <* br <*> text "Shipping date: " *> inputDate <* br <*> text "Qty: " *> inputInt <* br member x.Index() = x.ViewData.["Message"] <- "Welcome to ASP.NET MVC!" x.View(box <| render formlet) :> ActionResult member x.Register() = let env = fromNV x.Request.Form let name,orderDate,shippingDate,amount = run formlet env x.ViewData.["Name"] <- name x.ViewData.["Ordered"] <- orderDate x.ViewData.["Shipping"] <- shippingDate x.ViewData.["Amount"] <- amount x.View() :> ActionResult F# Web Snippets Index.aspx: <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Home Page </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2><%: ViewData["Message"] %></h2> <p> <% using (Html.BeginForm("Register", "Home")) { %> <%= Model%> <input type="submit" value="Submit" /> <% } %> </p> </asp:Content> Register.aspx <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Register </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <%: ViewData["Ordered"] %>: <%: ViewData["Name"] %> has requested <%: ViewData["Amount"] %> items to be delivered on <%: ViewData["Shipping"] %> </asp:Content> You can hover over any value on the F# snippets in this post and get a tooltip with types, thanks to F# Web Snippets. If you read my previous articles on applicative functors you'll recognize the standard operations pure (or puree), <*> and lift. Note how the final formlet is composed from more basic formlets: one that models date input, which in turn uses an formlet to input integers. They all rely on a primitive input formlet (of type string Formlet) that models an <input type="text"/>. Also note that we didn't define the name attribute for any input; formlets generate them automatically and also match them when handling submitted values. Running the app shows a form like this: First thing that should spring to your mind when seeing this is "boy, this is ugly", otherwise I'm not doing my job right :) Let's see now, step by step, how formlets can be implemented. We start by defining the types. First, a simple model of XML to represent HTML: type xml_item = | Text of string | Tag of string * (string*string) list * xml_item list // name * attributes * children We define an environment that will hold key-value pairs from submitted forms: type Env = (string*string) list And finally, the Formlet type: type 'a Formlet = int -> (xml_item list * (Env -> 'a) * int) Type signatures carry a lot of information, so let's take a moment to read this. It's a function that takes an int and returns a tuple of stuff. We'll see that the int it takes is used to generate the form element name. The tuple of stuff returned contains: an XML forest (representing HTML), a function we'll call collector, and an int that will be used to generate the next form element name. The collector is used to lookup the submitted value from the environment. A formlet is an applicative functor, so let's define puree: [<AutoOpen>] module Formlet = let puree (v: 'a) : 'a Formlet = fun i -> [], (fun _ -> v), i It's an empty XML, a constant collector, and the same input i. Here's the definition of <*> : let (<*>) (f: ('a -> 'b) Formlet) (a: 'a Formlet) : 'b Formlet = fun i -> let x1,g,i = f i let x2,q,i = a i x1 @ x2, (fun env -> g env (q env)), i Step by step: we apply f, since it holds an 'a -> 'b, the collector g collects a function 'a -> 'b. Then we apply a. We return the concatenation of XML forests, the composition of collectors, and the final name seed. Now some standard functions for applicative functors: let lift f a = puree f <*> a let lift2 f a b : _ Formlet = puree f <*> a <*> b let ( *>) f a : _ Formlet = lift2 (fun _ z -> z) f a let ( <*) f a : _ Formlet = lift2 (fun z _ -> z) f a A couple of functions to lift pure markup and text: let xml (x: xml_item list) : unit Formlet = fun i -> x, (fun _ -> ()), i let text (t: string) : unit Formlet = xml [Text t] The tag function creates a tag that wraps a formlet: let tag (name: string) (attr: (string*string) list) (f: 'a Formlet) : 'a Formlet = fun i -> let xml,env,i = f i [Tag(name, attr, xml)],env,i nextName is responsible for generating form element names: let nextName = fun i -> "input_" + i.ToString(), i+1 Note that it returns an incremented counter, to be used in the following name. The input primitive: let input : string Formlet = fun i -> let name,i = nextName i let collector = List.find (fun (k,_) -> k = name) >> snd let tag = Tag("input", ["name",name], []) [tag], collector, i The input formlet shows how everything fits together. It generates a fresh name to be used both in the collector and the input tag. This is what keeps the rendered form element and its respective collected value in sync. Here's a simple <br/> for formatting: let br: unit Formlet = xml [Tag("br",[],[])] The run function gets the collector of a formlet, which in turn will produce the collected value when applied to the environment: let run (f: 'a Formlet) : Env -> 'a = let _,e,_ = f 0 e That zero is the seed for form element names. We render a formlet by mapping it to a System.Xml.Linq.XDocument: open System.Xml.Linq let render (f: 'a Formlet) : XDocument = let xml,_,_ = f 0 let (!!) t = XName.op_Implicit t let xtext (s: string) = XText s :> XObject let xattr (name, value) = XAttribute(!!name, value) :> XObject let xattrs attr = List.map xattr attr let xelem name attr children = XElement(!!name, attr @ children) :> XObject let rec renderForest x = let render' = function | Text t -> xtext t | Tag(name, attr, children) -> xelem name (xattrs attr) (renderForest children) List.map render' x let root = xelem "div" [] (renderForest xml) XDocument root A helper function to make an Env from a NameValueCollection (such as Request.Form): open System.Collections.Specialized let fromNV (a: NameValueCollection) = a.AllKeys |> Seq.collect (fun k -> a.GetValues k |> Seq.map (fun v -> k,v)) |> Seq.toList Even though this was a bare bones implementation of formlets, I hope it served to illustrate how they work. This implementation was taken almost verbatim from the paper The Essence of Form Abstraction [PDF] by the original developers of Formlets mentioned at the beginning of this article. I kept it as simple and clear as possible, with many type annotations that weren't really necessary and intentionally cutting out features. Full source code is here. Next, we'll see how formlets can be factored to a composition of primitive applicatives. namespace Formlets union case xml_item.Text: string -> xml_item Multiple items val string : 'T -> string Full name: Microsoft.FSharp.Core.Operators.string -------------------- type string = System.String Full name: Microsoft.FSharp.Core.string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> union case xml_item.Tag: string * (string * string) list * xml_item list -> xml_item type 'T list = List<'T> Full name: Microsoft.FSharp.Collections.list<_>   type: 'T list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<'T>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'T>   implements: System.Collections.IEnumerable type xml_item =   | Text of string   | Tag of string * (string * string) list * xml_item list Full name: Formlets.xml_item   type: xml_item   implements: System.IEquatable<xml_item>   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<xml_item>   implements: System.IComparable   implements: System.Collections.IStructuralComparable type Env = (string * string) list Full name: Formlets.Env   type: Env   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<string * string>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<string * string>   implements: System.Collections.IEnumerable type 'a Formlet = int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet<_> Multiple items val int : 'T -> int (requires member op_Explicit) Full name: Microsoft.FSharp.Core.Operators.int -------------------- type int<'Measure> = int Full name: Microsoft.FSharp.Core.int<_>   type: int<'Measure>   implements: System.IComparable   implements: System.IConvertible   implements: System.IFormattable   implements: System.IComparable<int<'Measure>>   implements: System.IEquatable<int<'Measure>>   inherits: System.ValueType -------------------- type int = int32 Full name: Microsoft.FSharp.Core.int   type: int   implements: System.IComparable   implements: System.IFormattable   implements: System.IConvertible   implements: System.IComparable<int>   implements: System.IEquatable<int>   inherits: System.ValueType type AutoOpenAttribute =   class     inherit System.Attribute     new : unit -> AutoOpenAttribute     new : path:string -> AutoOpenAttribute     member Path : string   end Full name: Microsoft.FSharp.Core.AutoOpenAttribute   type: AutoOpenAttribute   implements: System.Runtime.InteropServices._Attribute   inherits: System.Attribute val puree : 'a -> int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet.puree val v : 'a val i : int   type: int   implements: System.IComparable   implements: System.IFormattable   implements: System.IConvertible   implements: System.IComparable<int>   implements: System.IEquatable<int>   inherits: System.ValueType val f : ('a -> 'b) Formlet val a : 'a Formlet val x1 : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<xml_item>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<xml_item>   implements: System.Collections.IEnumerable val g : (Env -> 'a -> 'b) val x2 : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<xml_item>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<xml_item>   implements: System.Collections.IEnumerable val q : (Env -> 'a) val env : Env   type: Env   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<string * string>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<string * string>   implements: System.Collections.IEnumerable val lift : ('a -> 'b) -> 'a Formlet -> 'b Formlet Full name: Formlets.Formlet.lift val f : ('a -> 'b) val lift2 : ('a -> 'b -> 'c) -> 'a Formlet -> 'b Formlet -> 'c Formlet Full name: Formlets.Formlet.lift2 val f : ('a -> 'b -> 'c) val b : 'b Formlet val f : 'a Formlet val a : 'b Formlet val z : 'b val z : 'a val xml : xml_item list -> int -> xml_item list * (Env -> unit) * int Full name: Formlets.Formlet.xml val x : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<xml_item>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<xml_item>   implements: System.Collections.IEnumerable type unit = Unit Full name: Microsoft.FSharp.Core.unit   type: unit   implements: System.IComparable val text : string -> unit Formlet Full name: Formlets.Formlet.text val t : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> val tag : string -> (string * string) list -> 'a Formlet -> int -> xml_item list * (Env -> 'a) * int Full name: Formlets.Formlet.tag val name : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> val attr : (string * string) list   type: (string * string) list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<string * string>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<string * string>   implements: System.Collections.IEnumerable val xml : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<xml_item>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<xml_item>   implements: System.Collections.IEnumerable val env : (Env -> 'a) val nextName : int -> string * int Full name: Formlets.Formlet.nextName Multiple overloads System.Object.ToString() : string System.Int32.ToString(provider: System.IFormatProvider) : string System.Int32.ToString(format: string) : string System.Int32.ToString(format: string, provider: System.IFormatProvider) : string val input : int -> xml_item list * (Env -> string) * int Full name: Formlets.Formlet.input val lookup : ((string * string) list -> string) Multiple items module List from Microsoft.FSharp.Collections -------------------- type List<'T> =   | ( [] )   | ( :: ) of 'T * 'T list   with     interface System.Collections.IEnumerable     interface System.Collections.Generic.IEnumerable<'T>     member Head : 'T     member IsEmpty : bool     member Item : index:int -> 'T with get     member Length : int     member Tail : 'T list     static member Cons : head:'T * tail:'T list -> 'T list     static member Empty : 'T list   end Full name: Microsoft.FSharp.Collections.List<_>   type: List<'T>   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<'T>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'T>   implements: System.Collections.IEnumerable val find : ('T -> bool) -> 'T list -> 'T Full name: Microsoft.FSharp.Collections.List.find val k : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> val snd : ('T1 * 'T2) -> 'T2 Full name: Microsoft.FSharp.Core.Operators.snd val tag : xml_item   type: xml_item   implements: System.IEquatable<xml_item>   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<xml_item>   implements: System.IComparable   implements: System.Collections.IStructuralComparable val br : unit Formlet Full name: Formlets.Formlet.br val run : 'a Formlet -> (Env -> 'a) Full name: Formlets.Formlet.run val e : (Env -> 'a) namespace System namespace System.Xml namespace System.Xml.Linq val render : 'a Formlet -> XDocument Full name: Formlets.Formlet.render type XDocument =   class     inherit System.Xml.Linq.XContainer     new : unit -> System.Xml.Linq.XDocument     new : obj [] -> System.Xml.Linq.XDocument     new : System.Xml.Linq.XDeclaration * obj [] -> System.Xml.Linq.XDocument     new : System.Xml.Linq.XDocument -> System.Xml.Linq.XDocument     member Declaration : System.Xml.Linq.XDeclaration with get, set     member DocumentType : System.Xml.Linq.XDocumentType     member NodeType : System.Xml.XmlNodeType     member Root : System.Xml.Linq.XElement     member Save : string -> unit     member Save : System.IO.TextWriter -> unit     member Save : System.Xml.XmlWriter -> unit     member Save : string * System.Xml.Linq.SaveOptions -> unit     member Save : System.IO.TextWriter * System.Xml.Linq.SaveOptions -> unit     member WriteTo : System.Xml.XmlWriter -> unit     static member Load : string -> System.Xml.Linq.XDocument     static member Load : System.IO.TextReader -> System.Xml.Linq.XDocument     static member Load : System.Xml.XmlReader -> System.Xml.Linq.XDocument     static member Load : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Load : System.IO.TextReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Load : System.Xml.XmlReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument     static member Parse : string -> System.Xml.Linq.XDocument     static member Parse : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XDocument   end Full name: System.Xml.Linq.XDocument   type: XDocument   implements: System.Xml.IXmlLineInfo   inherits: XContainer   inherits: XNode   inherits: XObject type XName =   class     member Equals : obj -> bool     member GetHashCode : unit -> int     member LocalName : string     member Namespace : System.Xml.Linq.XNamespace     member NamespaceName : string     member ToString : unit -> string     static member Get : string -> System.Xml.Linq.XName     static member Get : string * string -> System.Xml.Linq.XName   end Full name: System.Xml.Linq.XName   type: XName   implements: System.IEquatable<XName>   implements: System.Runtime.Serialization.ISerializable XName.op_Implicit(expandedName: string) : XName val xtext : (string -> XObject) val s : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> type XText =   class     inherit System.Xml.Linq.XNode     new : string -> System.Xml.Linq.XText     new : System.Xml.Linq.XText -> System.Xml.Linq.XText     member NodeType : System.Xml.XmlNodeType     member Value : string with get, set     member WriteTo : System.Xml.XmlWriter -> unit   end Full name: System.Xml.Linq.XText   type: XText   implements: System.Xml.IXmlLineInfo   inherits: XNode   inherits: XObject type XObject =   class     member AddAnnotation : obj -> unit     member Annotation<'T> : unit -> 'T     member Annotation : System.Type -> obj     member Annotations<'T> : unit -> System.Collections.Generic.IEnumerable<'T>     member Annotations : System.Type -> System.Collections.Generic.IEnumerable<obj>     member BaseUri : string     member Document : System.Xml.Linq.XDocument     member NodeType : System.Xml.XmlNodeType     member Parent : System.Xml.Linq.XElement     member RemoveAnnotations<'T> : unit -> unit     member RemoveAnnotations : System.Type -> unit   end Full name: System.Xml.Linq.XObject   type: XObject   implements: System.Xml.IXmlLineInfo val xattr : (string * 'b -> XObject) val value : 'b type XAttribute =   class     inherit System.Xml.Linq.XObject     new : System.Xml.Linq.XName * obj -> System.Xml.Linq.XAttribute     new : System.Xml.Linq.XAttribute -> System.Xml.Linq.XAttribute     member IsNamespaceDeclaration : bool     member Name : System.Xml.Linq.XName     member NextAttribute : System.Xml.Linq.XAttribute     member NodeType : System.Xml.XmlNodeType     member PreviousAttribute : System.Xml.Linq.XAttribute     member Remove : unit -> unit     member SetValue : obj -> unit     member ToString : unit -> string     member Value : string with get, set     static member EmptySequence : System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>   end Full name: System.Xml.Linq.XAttribute   type: XAttribute   implements: System.Xml.IXmlLineInfo   inherits: XObject val xattrs : ((string * 'b) list -> XObject list) val attr : (string * 'b) list   type: (string * 'b) list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<string * 'b>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<string * 'b>   implements: System.Collections.IEnumerable val map : ('T -> 'U) -> 'T list -> 'U list Full name: Microsoft.FSharp.Collections.List.map val xelem : (string -> 'b list -> 'b list -> XObject) val attr : 'b list   type: 'b list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<'b>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'b>   implements: System.Collections.IEnumerable val children : 'b list   type: 'b list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<'b>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<'b>   implements: System.Collections.IEnumerable type XElement =   class     inherit System.Xml.Linq.XContainer     new : System.Xml.Linq.XName -> System.Xml.Linq.XElement     new : System.Xml.Linq.XName * obj -> System.Xml.Linq.XElement     new : System.Xml.Linq.XName * obj [] -> System.Xml.Linq.XElement     new : System.Xml.Linq.XElement -> System.Xml.Linq.XElement     new : System.Xml.Linq.XStreamingElement -> System.Xml.Linq.XElement     member AncestorsAndSelf : unit -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>     member AncestorsAndSelf : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>     member Attribute : System.Xml.Linq.XName -> System.Xml.Linq.XAttribute     member Attributes : unit -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>     member Attributes : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>     member DescendantNodesAndSelf : unit -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XNode>     member DescendantsAndSelf : unit -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>     member DescendantsAndSelf : System.Xml.Linq.XName -> System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>     member FirstAttribute : System.Xml.Linq.XAttribute     member GetDefaultNamespace : unit -> System.Xml.Linq.XNamespace     member GetNamespaceOfPrefix : string -> System.Xml.Linq.XNamespace     member GetPrefixOfNamespace : System.Xml.Linq.XNamespace -> string     member HasAttributes : bool     member HasElements : bool     member IsEmpty : bool     member LastAttribute : System.Xml.Linq.XAttribute     member Name : System.Xml.Linq.XName with get, set     member NodeType : System.Xml.XmlNodeType     member RemoveAll : unit -> unit     member RemoveAttributes : unit -> unit     member ReplaceAll : obj -> unit     member ReplaceAll : obj [] -> unit     member ReplaceAttributes : obj -> unit     member ReplaceAttributes : obj [] -> unit     member Save : string -> unit     member Save : System.IO.TextWriter -> unit     member Save : System.Xml.XmlWriter -> unit     member Save : string * System.Xml.Linq.SaveOptions -> unit     member Save : System.IO.TextWriter * System.Xml.Linq.SaveOptions -> unit     member SetAttributeValue : System.Xml.Linq.XName * obj -> unit     member SetElementValue : System.Xml.Linq.XName * obj -> unit     member SetValue : obj -> unit     member Value : string with get, set     member WriteTo : System.Xml.XmlWriter -> unit     static member EmptySequence : System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>     static member Load : string -> System.Xml.Linq.XElement     static member Load : System.IO.TextReader -> System.Xml.Linq.XElement     static member Load : System.Xml.XmlReader -> System.Xml.Linq.XElement     static member Load : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Load : System.IO.TextReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Load : System.Xml.XmlReader * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement     static member Parse : string -> System.Xml.Linq.XElement     static member Parse : string * System.Xml.Linq.LoadOptions -> System.Xml.Linq.XElement   end Full name: System.Xml.Linq.XElement   type: XElement   implements: System.Xml.IXmlLineInfo   implements: System.Xml.Serialization.IXmlSerializable   inherits: XContainer   inherits: XNode   inherits: XObject val renderForest : (xml_item list -> XObject list) val render' : (xml_item -> XObject) val children : xml_item list   type: xml_item list   implements: System.Collections.IStructuralEquatable   implements: System.IComparable<List<xml_item>>   implements: System.IComparable   implements: System.Collections.IStructuralComparable   implements: System.Collections.Generic.IEnumerable<xml_item>   implements: System.Collections.IEnumerable val root : XObject   type: XObject   implements: System.Xml.IXmlLineInfo namespace System.Collections namespace System.Collections.Specialized val fromNV : NameValueCollection -> (string * string) list Full name: Formlets.Formlet.fromNV val a : NameValueCollection   type: NameValueCollection   implements: System.Collections.ICollection   implements: System.Collections.IEnumerable   implements: System.Runtime.Serialization.ISerializable   implements: System.Runtime.Serialization.IDeserializationCallback   inherits: NameObjectCollectionBase type NameValueCollection =   class     inherit System.Collections.Specialized.NameObjectCollectionBase     new : unit -> System.Collections.Specialized.NameValueCollection     new : System.Collections.Specialized.NameValueCollection -> System.Collections.Specialized.NameValueCollection     new : System.Collections.IHashCodeProvider * System.Collections.IComparer -> System.Collections.Specialized.NameValueCollection     new : int -> System.Collections.Specialized.NameValueCollection     new : System.Collections.IEqualityComparer -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.IEqualityComparer -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.Specialized.NameValueCollection -> System.Collections.Specialized.NameValueCollection     new : int * System.Collections.IHashCodeProvider * System.Collections.IComparer -> System.Collections.Specialized.NameValueCollection     member Add : System.Collections.Specialized.NameValueCollection -> unit     member Add : string * string -> unit     member AllKeys : string []     member Clear : unit -> unit     member CopyTo : System.Array * int -> unit     member Get : string -> string     member Get : int -> string     member GetKey : int -> string     member GetValues : string -> string []     member GetValues : int -> string []     member HasKeys : unit -> bool     member Item : string -> string with get, set     member Item : int -> string     member Remove : string -> unit     member Set : string * string -> unit   end Full name: System.Collections.Specialized.NameValueCollection   type: NameValueCollection   implements: System.Collections.ICollection   implements: System.Collections.IEnumerable   implements: System.Runtime.Serialization.ISerializable   implements: System.Runtime.Serialization.IDeserializationCallback   inherits: NameObjectCollectionBase property NameValueCollection.AllKeys: string [] module Seq from Microsoft.FSharp.Collections val collect : ('T -> #seq<'U>) -> seq<'T> -> seq<'U> Full name: Microsoft.FSharp.Collections.Seq.collect Multiple overloads NameValueCollection.GetValues(index: int) : string [] NameValueCollection.GetValues(name: string) : string [] val map : ('T -> 'U) -> seq<'T> -> seq<'U> Full name: Microsoft.FSharp.Collections.Seq.map val v : string   type: string   implements: System.IComparable   implements: System.ICloneable   implements: System.IConvertible   implements: System.IComparable<string>   implements: seq<char>   implements: System.Collections.IEnumerable   implements: System.IEquatable<string> val toList : seq<'T> -> 'T list Full name: Microsoft.FSharp.Collections.Seq.toList namespace System.Web namespace System.Web.Mvc namespace System.Collections.Generic type HandleErrorAttribute =   class     inherit System.Web.Mvc.FilterAttribute     new : unit -> System.Web.Mvc.HandleErrorAttribute     member ExceptionType : System.Type with get, set     member Master : string with get, set     member OnException : System.Web.Mvc.ExceptionContext -> unit     member View : string with get, set   end Full name: System.Web.Mvc.HandleErrorAttribute   type: HandleErrorAttribute   implements: Runtime.InteropServices._Attribute   implements: IExceptionFilter   inherits: FilterAttribute   inherits: Attribute type HomeController =   class     inherit Controller     new : unit -> HomeController     member Index : unit -> ActionResult     member Register : unit -> ActionResult   end Full name: Formlets.HomeController   type: HomeController   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: Controller   inherits: ControllerBase   inherits: MarshalByRefObject type Controller =   class     inherit System.Web.Mvc.ControllerBase     member ActionInvoker : System.Web.Mvc.IActionInvoker with get, set     member Dispose : unit -> unit     member HttpContext : System.Web.HttpContextBase     member ModelState : System.Web.Mvc.ModelStateDictionary     member Request : System.Web.HttpRequestBase     member Response : System.Web.HttpResponseBase     member RouteData : System.Web.Routing.RouteData     member Server : System.Web.HttpServerUtilityBase     member Session : System.Web.HttpSessionStateBase     member TempDataProvider : System.Web.Mvc.ITempDataProvider with get, set     member Url : System.Web.Mvc.UrlHelper with get, set     member User : System.Security.Principal.IPrincipal   end Full name: System.Web.Mvc.Controller   type: Controller   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: ControllerBase   inherits: MarshalByRefObject val inputInt : int Formlet Multiple items val int : 'T -> int (requires member op_Explicit) Full name: Microsoft.FSharp.Core.Operators.int -------------------- type int<'Measure> = int Full name: Microsoft.FSharp.Core.int<_>   type: int<'Measure>   implements: IComparable   implements: IConvertible   implements: IFormattable   implements: IComparable<int<'Measure>>   implements: IEquatable<int<'Measure>>   inherits: ValueType -------------------- type int = int32 Full name: Microsoft.FSharp.Core.int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable<int>   implements: IEquatable<int>   inherits: ValueType val inputDate : DateTime Formlet val month : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable<int>   implements: IEquatable<int>   inherits: ValueType val day : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable<int>   implements: IEquatable<int>   inherits: ValueType val year : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable<int>   implements: IEquatable<int>   inherits: ValueType type DateTime =   struct     new : int64 -> System.DateTime     new : int64 * System.DateTimeKind -> System.DateTime     new : int * int * int -> System.DateTime     new : int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int -> System.DateTime     new : int * int * int * int * int * int * System.DateTimeKind -> System.DateTime     new : int * int * int * int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int * int -> System.DateTime     new : int * int * int * int * int * int * int * System.DateTimeKind -> System.DateTime     new : int * int * int * int * int * int * int * System.Globalization.Calendar -> System.DateTime     new : int * int * int * int * int * int * int * System.Globalization.Calendar * System.DateTimeKind -> System.DateTime     member Add : System.TimeSpan -> System.DateTime     member AddDays : float -> System.DateTime     member AddHours : float -> System.DateTime     member AddMilliseconds : float -> System.DateTime     member AddMinutes : float -> System.DateTime     member AddMonths : int -> System.DateTime     member AddSeconds : float -> System.DateTime     member AddTicks : int64 -> System.DateTime     member AddYears : int -> System.DateTime     member CompareTo : obj -> int     member CompareTo : System.DateTime -> int     member Date : System.DateTime     member Day : int     member DayOfWeek : System.DayOfWeek     member DayOfYear : int     member Equals : obj -> bool     member Equals : System.DateTime -> bool     member GetDateTimeFormats : unit -> string []     member GetDateTimeFormats : System.IFormatProvider -> string []     member GetDateTimeFormats : char -> string []     member GetDateTimeFormats : char * System.IFormatProvider -> string []     member GetHashCode : unit -> int     member GetTypeCode : unit -> System.TypeCode     member Hour : int     member IsDaylightSavingTime : unit -> bool     member Kind : System.DateTimeKind     member Millisecond : int     member Minute : int     member Month : int     member Second : int     member Subtract : System.DateTime -> System.TimeSpan     member Subtract : System.TimeSpan -> System.DateTime     member Ticks : int64     member TimeOfDay : System.TimeSpan     member ToBinary : unit -> int64     member ToFileTime : unit -> int64     member ToFileTimeUtc : unit -> int64     member ToLocalTime : unit -> System.DateTime     member ToLongDateString : unit -> string     member ToLongTimeString : unit -> string     member ToOADate : unit -> float     member ToShortDateString : unit -> string     member ToShortTimeString : unit -> string     member ToString : unit -> string     member ToString : string -> string     member ToString : System.IFormatProvider -> string     member ToString : string * System.IFormatProvider -> string     member ToUniversalTime : unit -> System.DateTime     member Year : int     static val MinValue : System.DateTime     static val MaxValue : System.DateTime     static member Compare : System.DateTime * System.DateTime -> int     static member DaysInMonth : int * int -> int     static member Equals : System.DateTime * System.DateTime -> bool     static member FromBinary : int64 -> System.DateTime     static member FromFileTime : int64 -> System.DateTime     static member FromFileTimeUtc : int64 -> System.DateTime     static member FromOADate : float -> System.DateTime     static member IsLeapYear : int -> bool     static member Now : System.DateTime     static member Parse : string -> System.DateTime     static member Parse : string * System.IFormatProvider -> System.DateTime     static member Parse : string * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member ParseExact : string * string * System.IFormatProvider -> System.DateTime     static member ParseExact : string * string * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member ParseExact : string * string [] * System.IFormatProvider * System.Globalization.DateTimeStyles -> System.DateTime     static member SpecifyKind : System.DateTime * System.DateTimeKind -> System.DateTime     static member Today : System.DateTime     static member TryParse : string * System.DateTime -> bool     static member TryParse : string * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member TryParseExact : string * string * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member TryParseExact : string * string [] * System.IFormatProvider * System.Globalization.DateTimeStyles * System.DateTime -> bool     static member UtcNow : System.DateTime   end Full name: System.DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable<DateTime>   implements: IEquatable<DateTime>   inherits: ValueType val formlet : (string * DateTime * DateTime * int) Formlet val name : string   type: string   implements: IComparable   implements: ICloneable   implements: IConvertible   implements: IComparable<string>   implements: seq<char>   implements: Collections.IEnumerable   implements: IEquatable<string> val order : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable<DateTime>   implements: IEquatable<DateTime>   inherits: ValueType val ship : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable<DateTime>   implements: IEquatable<DateTime>   inherits: ValueType val amount : int   type: int   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: IComparable<int>   implements: IEquatable<int>   inherits: ValueType val x : HomeController   type: HomeController   implements: IController   implements: IActionFilter   implements: IAuthorizationFilter   implements: IDisposable   implements: IExceptionFilter   implements: IResultFilter   inherits: Controller   inherits: ControllerBase   inherits: MarshalByRefObject member HomeController.Index : unit -> ActionResult Full name: Formlets.HomeController.Index property ControllerBase.ViewData: ViewDataDictionary Multiple overloads Controller.View() : ViewResult Controller.View(view: IView) : ViewResult Controller.View(viewName: string) : ViewResult Controller.View(model: obj) : ViewResult Controller.View(view: IView, model: obj) : ViewResult Controller.View(viewName: string, model: obj) : ViewResult Controller.View(viewName: string, masterName: string) : ViewResult Controller.View(viewName: string, masterName: string, model: obj) : ViewResult val box : 'T -> obj Full name: Microsoft.FSharp.Core.Operators.box val render : 'a Formlet -> Xml.Linq.XDocument Full name: Formlets.Formlet.render type ActionResult =   class     member ExecuteResult : System.Web.Mvc.ControllerContext -> unit   end Full name: System.Web.Mvc.ActionResult member HomeController.Register : unit -> ActionResult Full name: Formlets.HomeController.Register val env : (string * string) list   type: (string * string) list   implements: Collections.IStructuralEquatable   implements: IComparable<List<string * string>>   implements: IComparable   implements: Collections.IStructuralComparable   implements: IEnumerable<string * string>   implements: Collections.IEnumerable val fromNV : Collections.Specialized.NameValueCollection -> (string * string) list Full name: Formlets.Formlet.fromNV property Controller.Request: HttpRequestBase property HttpRequestBase.Form: Collections.Specialized.NameValueCollection val orderDate : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable<DateTime>   implements: IEquatable<DateTime>   inherits: ValueType val shippingDate : DateTime   type: DateTime   implements: IComparable   implements: IFormattable   implements: IConvertible   implements: Runtime.Serialization.ISerializable   implements: IComparable<DateTime>   implements: IEquatable<DateTime>   inherits: ValueType [Less]