Showing posts with label applicative functors. Show all posts
Showing posts with label applicative functors. Show all posts

Monday, July 30, 2012

A tale of equational reasoning in F#

My implementation of formlets, based on the original paper, composes quite a few applicative functors. They're all standard applicatives. For example, the one that looks up values from the submitted form is just a specialized Reader (i.e. a Reader with one of the type parameters fixed to the form type). The applicative responsible for generating form element names is a State. Another two of the applicatives are actually the same applicative, only specialized with different type parameters.

Since many of these are already implemented in FSharpx, I decided to use those implementations instead... After making the necessary changes and getting it to compile, I ran the tests and got a lot of failures. Many of the outputs involving lists were exactly in inverse order! I traced it down to the composition of applicatives, but I couldn't figure out what was wrong.

I'll illustrate with a simple but concrete example. We'll use the Writer applicative. Essentially, the effect of this applicative is appending values with a monoid. Here we'll just accumulate on a list.

This is much simpler to see in code:

let puree x = [],x 
let ap (x1,x2) (f1,f2) = f1 @ x1, f2 x2 

An example using it:

puree (-) |> ap (["a";"b"],3) |> ap (["c";"d"],2)

This evaluates to (["a"; "b"; "c"; "d"], 1) , i.e. it concatenates the lists (the effect) and applies the function to the second value in the tuple.

So far so good. Now let's try to compose this applicative with itself. Composing applicatives is easy: as I explained in a previous article, just lift ap and apply pure to pure:

let lift2 f a b = puree f |> ap a |> ap b

let composedPure x = x |> puree |> puree 
let composedAp x f = lift2 ap x f

Let's see how this works:

composedPure (-) 
|> composedAp (["a"; "b"], ([1; 2], 2)) 
|> composedAp (["c"; "d"], ([3; 4], 3))

which gives us (["c"; "d"; "a"; "b"], ([1; 2; 3; 4], -1))

Uh oh, the outer applicative has its effect flipped! The result should have been (["a"; "b"; "c"; "d"], ([1; 2; 3; 4], -1)) . What went wrong here?

One difference in this code with the Haskell definition of applicative functors is that I flipped the parameters of ap. This allowed us to apply ap with a pipe as is usual in F#. You could also use a forward and a backward pipe to "infixify" a function but it just doesn't look right to me. Even though it compiles and apparently looks correct, this difference broke our applicative composition.

In order to fix the applicative composition and still keep the convenient flipped parameters, we have to change composedAp to:

let flip f a b = f b a

let composedAp x f = flip (lift2 (flip ap)) x f

The question now is: do you really understand why this composedAp is correct, just by looking at its definition, while the previous one would flip one of the applicatives and not the other?

To be honest, I don't. But simple equational reasoning can tell us what went wrong. Let's start with the original (incorrect) definition of composedAp:

  lift2 ap x f 
= puree ap |> ap x |> ap f              // lift2 definition
= ap f (ap x (puree ap))                // |> definition
= ap (f1,f2) (ap (x1,x2) (pap1, pap2))  // expand tuples, apply puree
= ap (f1,f2) (pap1 @ x1, pap2 x2)       // apply inner ap
= pap1 @ x1 @ f1, pap2 x2 f2            // apply outer ap
= [] @ x1 @ f1, ap x2 f2                // apply puree
= x1 @ f1, ap (x21, x22) (f21, f22)     // simplify empty list, expand tuples
= x1 @ f1, (f21 @ x21, f22 x22)         // apply ap

Now the correct composedAp, for comparison:

flip (lift2 (flip ap)) x f 
= flip (fun f a b -> ap b (ap a (puree (flip ap)))) x f     // lift2 definition
= (fun f a b -> ap b (ap a (puree (flip ap)))) f x          // apply flip
= ap x (ap f (puree (flip ap)))                             // apply lambda
= ap (x1,x2) (ap (f1,f2) (pfap1, pfap2))                    // expand tuples, apply puree
= ap (x1,x2) (pfap1 @ f1, pfap2 f2)                         // apply ap
= pfap1 @ f1 @ x1, pfap2 f2 x2                              // apply ap
= [] @ f1 @ x1, (flip ap) f2 x2                             // puree
= f1 @ x1, ap x2 f2                                         // simplify empty list, apply flip
= f1 @ x1, ap (x21, x22) (f21, f22)                         // expand tuples
= f1 @ x1, (f21 @ x21, f22 x22)                             // apply ap

By comparing both you can get a better understanding of why two flips are necessary.

Reasoning like this is a simple but powerful tool. We kinda do it continuously, informally, while writing code, which is usually called "running the program in your head". The absence of side-effects (i.e. pure functional programming) makes it easier to do it formally as well as informally, since you typically need to juggle less stuff in your head.

Thursday, March 29, 2012

An example of applicative validation in FSharpx

I recently found a nice example of applicative functor validation in Scala (using Scalaz) by Chris Marshall, and decided to port it to F# and C# using FSharpx.

I blogged about applicative functor validation before, in F# and in C#.

When trying to port the Scala code to F# I found there were a few missing general functions in FSharpx, notably sequence and mapM. These are one- or two-liners, I ported them from Haskell, as it's syntactically closer to F# than Scala. Hoogle is always a big help for this.

Here is the original code in Scala; here's the F# port and here's the C# port.
I'm not going to copy it here: it's 160 lines of F# and 250 lines of C#.

This example also makes for a nice comparison of these three languages (or four, if you count the implicit presence of Haskell). There are a few little differences in the ports, it's not a literal translation, but you can still see how Scala, being semantically closer to Haskell than either F# or C#, achieves more generality. As for type inference, the F# version requires almost no type annotations, while C# needs the most type annotations, and Scala is somewhere in the middle. This actually depends on what you consider a type annotation.

I chose to make Person immutable in C# to reflect more accurately the equivalent F# and Scala code, but it's not really instrumental to this example. Still, it shows how verbose it is to create a truly immutable class in C#. The C# dev team at Microsoft seems to highly value immutability, so I still have hopes that a future version of C# will improve this situation.

The ability to define custom operators in Scala and F#, like <!> or *> (an ability that C# lacks) also makes it easier to work with different ways of composing functions. FSharpx also offers 'named' versions for many of these operators, for example <!> is simply 'map' and <*> is 'ap'. Despite what some people say, I think custom operators enable better readability once you know the concepts behind them. Remember that at some point you also learned what '=', '%' and '+' mean.

In particular, the F# port shows the Kleisli composition operator >=> which I haven't seen mentioned in F# before. This operator is like the regular function composition operator >> except it works for monadic functions a -> m b. Compare the signatures for >> and >=> for Option:

(>>) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c (>=>) : ('a -> 'b option) -> ('b -> 'c option) -> 'a -> 'c option

I'm quite pleased with the results of this port, even if I do say so myself. This example shows again that many higher concepts in functional programming commonly applied in Haskell are applicable, useful and usable in F# and even in C#. The lack of typeclasses and type constructor abstraction in .NET means some code duplication (mapM for example has to be defined for each monad), but this duplication is on the side of library code in many cases, and so client code isn't that badly affected.

Homework: port this example to Gustavo's fork of FSharpx.

Monday, August 29, 2011

Validating with applicative functors in F#

In my last post I showed how to validate using applicative functors in C#. LINQ helps a lot with making the syntax bearable.

In F# we have other tools to encode applicative functors: custom operators and type inference. And thanks to pattern matching it's much easier to define the validation applicative functor operations in F# (but I won't show that here).

So let's see what the C# code from the last post looks like in F#. Hopefully this article will serve both C# developers interested in learning F# and F# developers interested in learning more about applicative functors. F# programmers will probably find the first part boring and might want to go directly to the second part.

Defining the primitives

Starting from the bottom up, here's the function that builds a validator from a predicate:

static Func<T, FSharpChoice<T, Errors>> Validator<T>(Predicate<T> pred, string error) {
    return x => {
        if (pred(x))
            return FSharpChoice.Ok(x);
        return FSharpChoice.Error<T>(error);
    };
}

Same thing in F#:

let validator pred error x =
    if pred x
        then Choice1Of2 x
        else Choice2Of2 [error]

We don't need the Ok and Error constructors because F# correctly infers the appropriate types. In fact, we did not use a single type annotation!

We don't need to explicitly state that we're returning a function, as we'll see now:

static FSharpChoice<T, Errors> NonNull<T>(T value, string err) where T: class {
    return Validator<T>(x => x != null, err)(value);
}

Same in F# :

let (==) = LanguagePrimitives.PhysicalEquality
let inline (!=) a b = not (a == b)

let nonNull e = validator ((!=) null) e

Readers unfamiliar with F# might wonder about the definition of == and !=. The answer is: F# doesn't have a built-in reference equality operator, and with good reason: usually you want to compare things by their structure rather than by reference. We could have used F# structural equality here (the <> operator in this case) but this would have placed an additional equality type restriction. It doesn't really matter in this case but we'll try to keep things as close as possible to the equivalent C# code. If you want to learn more about structural equality I refer you to this very thorough article by Brian McNamara.

C# programmers that are still paying any attention to this code (gotcha! ;-) should have noticed that I defined the validator function with three parameters (pred, error, x), yet I only defined the first two arguments when defining nonNull. Where did the other parameter go? This is an example of partial application of a curried function. Currying and partial application are often confused with each other, but they're not the same thing. Ivan Towlson has a great series of articles about partial application in F# and comparing it to C#. I also recomend this article (and related) by Dustin Campbell.

Moving on:

static FSharpChoice<T, Errors> NotEqual<T>(T value, T other, string err) {
    return Validator<T>(v => !Equals(v, other), err)(value);
}

Same in F# :

let notEqual a = validator ((<>) a)

Here we did use structural equality, we certainly don't want to compare things by reference. Object.Equals is not the same as F#'s structural equality. Something probably a little closer would be requiring T to implement IEquatable<T> in the C# function, but still not the same.

static Func<Address, FSharpChoice<Address, Errors>> ValidateAddressLines = 
    Validator<Address>(x => x.Line1 != null || x.Line2 == null, 
                       "Line1 is empty but Line2 is not");

Same in F# :

let validateAddressLines =
    validator 
        (fun (a: Address) -> a.Line1 != null || a.Line2 == null) 
        "Line1 is empty but Line2 is not"

Nothing interesting here. Next:

static FSharpChoice<T?, Errors> GreaterThan<T>(T? value, T? other, string err) where T: struct, IComparable<T> {
    if (!value.HasValue && !other.HasValue || value.HasValue != other.HasValue || value.Value.CompareTo(other.Value) > 0)
        return FSharpChoice.Ok(value);
    return FSharpChoice.Error<T?>(err);
}

The bad news here is that F# doesn't have built-in support for nullable types. Fortunately, it's not too hard to write a few functions and get decent syntax. I already did that about a year ago so I'll just use it here:

let greaterThan o = validator ((<?) o)

No, that's not a typo: due to the way operators are defined, they have to be read backwards when partially applied. You can be a bit more explicit/verbose and instead say:

let greaterThan o = validator (fun a -> a >? o)

Combining functions through monads and applicative functors

Now that we have all primitives defined, let's get to the interesting part: combine them with an applicative functor and monad.

I've blogged about applicative functors in F# many times... very briefly, there are two operations: pure (puree in F#) and apply (<*> in F#). And we define this convenience function (this is standard for applicative functors):

let inline (<!>) f x = puree f <*> x

Here's ValidateAddress() in C# using LINQ to encode the applicative functor:

static FSharpChoice<Address, Errors> ValidateAddress(Address a) {
    return from x in NonNull(a.Postcode, "Post code can't be null")
           join y in ValidateAddressLines(a) on 1 equals 1
           select a;
}

Here's the equivalent in F# :

let validateAddress (a: Address) = 
    fun x y -> a
    <!> nonNull "Post code can't be null" a.Postcode
    <*> validateAddressLines a

If you squint a little, they're not that different really. We can go a bit further to avoid having those dummy values x and y that we end up ignoring anyway. We only need to define (these are also standard functions):

let inline lift2 f a b = f <!> a <*> b
let inline ( <*) a b = lift2 (fun z _ -> z) a b

Now we can say:

let validateAddress (a: Address) = 
    puree a
    <* nonNull "Post code can't be null" a.Postcode
    <* validateAddressLines a

Validating a single Order in C#:

static FSharpChoice<Order, Errors> ValidateOrder(Order o) {
    return
        from name in NonNull(o.ProductName, "Product name can't be null")
        from cost in GreaterThan(o.Cost, 0, string.Format("Cost for product '{0}' must be positive", name))
        select o;
}

Unlike the previous validators, this one is monadic, not applicative. In F# we have some alternatives. We can use a computation expression:

let validateOrder (o: Order) =
    validation {
        let! name = nonNull "Product name can't be null" o.ProductName
        let! _ = greaterThan (0m).n (sprintf "Cost for product '%s' must be positive" name) o.Cost
        return o
    }

Or we can use monadic operators directly:

let validateOrder (o: Order) =
    let nameNotNull = nonNull "Product name can't be null" o.ProductName
    let positiveCost n = greaterThan (0m).n (sprintf "Cost for product '%s' can't be negative" n) o.Cost
    nameNotNull >>= positiveCost |> map (fun _ -> o)

The higher-order function to make this operate on sequences of orders:

static FSharpChoice<FSharpList<Order>, Errors> ValidateOrders(IEnumerable<Order> orders) {
    var zero = ListModule.Empty<Order>().PureValidate();
    return orders
        .Select(ValidateOrder)
        .Aggregate(zero, (e, c) => from a in e
                                   join b in c on 1 equals 1
                                   select a.Cons(b));
}

Same in F# :

let inline flip f a b = f b a
let inline cons a b = a::b
let seqValidator f = 
    let zero = puree []
    Seq.map f >> Seq.fold (lift2 (flip cons)) zero
let validateOrders c = seqValidator validateOrder c

And the final validations with an sample application:

let customer = 
    Customer(
        Surname = "foo",
        Address = Address(Postcode = "1424"),
        Orders = ResizeArray([
                                Order(ProductName = "Foo", Cost = (5m).n)
                                Order(ProductName = "Bar", Cost = (-1m).n)
                                Order(ProductName = null , Cost = (-1m).n)
                 ]))
let result = 
    puree customer
    <* nonNull "Surname can't be null" customer.Surname
    <* notEqual "foo" "Surname can't be foo" customer.Surname
    <* validateAddress customer.Address
    <* validateOrders customer.Orders
match result with
| Choice1Of2 c -> printfn "Valid customer: %A" c
| Choice2Of2 errors -> printfn "Invalid customer. Errors:\n%A" errors

Wrap it up already!

I know, I know, this post is too long already. Hopefully this step-by-step, side-by-side comparison will help C# programmers see some of the power of F# through currying, partial application, custom operators and type inference, in a non-trivial example. And F# developers can see another use for applicative functors: validation.

Code is here.

Monday, August 22, 2011

Validating with applicative functors and LINQ

In my last post I introduced the basics of validation with applicative functors. I used a very simple example that didn't make it justice, so let's fix that now. I'll borrow a more complex example from the FluentValidation wiki:

class Address {
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Town { get; set; }
    public string County { get; set; }
    public string Postcode { get; set; }        
}

class Order {
    public string ProductName { get; set; }
    public decimal? Cost { get; set; }
}

class Customer {
    public int Id { get; set; }
    public string Surname { get; set; }
    public string Forename { get; set; }
    public decimal Discount { get; set; }
    public Address Address { get; set; }
    public IList<Order> Orders { get; set; }
}

In this domain, we'll do a few somewhat arbitrary validations:

  • A customer's surname can't be null.
  • A customer's surname can't be 'Foo'.
  • An address postcode can't be null
  • Address lines are optional, but content in the second line is not allowed if there is no content in the first line.
  • An order's product name can't be null
  • If the order's product name is valid, check that its cost is positive.

Let's do this top-down; starting with the customer:

var customer = new Customer { ... }
var result =
    from surname in NonNull(customer.Surname, "Surname can't be null")
    join surname2 in NotEqual(customer.Surname, "foo", "Surname can't be foo") on 1 equals 1
    join address in ValidateAddress(customer.Address) on 1 equals 1
    join orders in ValidateOrders(customer.Orders) on 1 equals 1
    select customer;

surname, surname2, etc, are all dummies here, we never really use them. Now we'll describe each of these functions, starting with NonNull() which is almost trivial:

static FSharpChoice<T, Errors> NonNull<T>(T value, string err) where T: class {
    if (value == null)
        return FSharpChoice.Error<T>(err);
    return FSharpChoice.Ok(value);
}

where Errors is just a type alias for FSharpList<string>, and FSharpChoice.Error() and FSharpChoice.Ok() are just less-verbose FSharpChoice constructors for this purpose.

NotEqual() is similar and, just as one would expect, validates that a value is not equal to some other value and also returns a FSharpChoice<T, Errors>

Now let's see how ValidateAddress() looks like:

static FSharpChoice<Address, Errors> ValidateAddress(Address a) {
    return from x in NonNull(a.Postcode, "Post code can't be null")
           join y in ValidateAddressLines(a) on 1 equals 1
           select a;
}

Ok, but what's in ValidateAddressLines() ?

static FSharpChoice<Address, Errors> ValidateAddressLines(Address a) {
    if (a.Line1 != null || a.Line2 == null)
        return FSharpChoice.Ok(a);
    return FSharpChoice.Error<Address>("Line1 is empty but Line2 is not");
}

Note how both NonNull() and ValidateAddressLines() use the form "if condition then ok else error". It's a pretty common pattern so let's abstract that to a higher-order function:

static Func<T, FSharpChoice<T, Errors>> Validator<T>(Predicate<T> pred, string err) {
    return x => {
        if (pred(x))
            return FSharpChoice.Ok(x);
        return FSharpChoice.Error<T>(err);
    };
}

and now we can write:

static readonly Func<Address, FSharpChoice<Address, Errors>> ValidateAddressLines =
    Validator<Address>(x => x.Line1 != null || x.Line2 == null, 
                       "Line1 is empty but Line2 is not");

Only ValidateOrders() is left to explain. Let's see first how to validate a single order, and then we'll figure out how to make that operate on a list of orders:

static FSharpChoice<Order, Errors> ValidateOrder(Order o) {
    return
        from name in NonNull(o.ProductName, "Product name can't be null")
        from cost in GreaterThan(o.Cost, 0, string.Format("Cost for product '{0}' can't be negative", name))
        select o;
}

Here we used monadic validation (from...from...) which, as explained before, causes the second validation to run only if the first was successful.

Now the tricky part: making this work on IEnumerable<Order>. I'll use explicit types here so you can better see what's going on in each step, and inline comments:

static FSharpChoice<IEnumerable<Order>, Errors> ValidateOrders(IEnumerable<Order> orders) {
    // first we apply the validator to all orders
    IEnumerable<FSharpChoice<Order,Errors>> validatedOrders = orders.Select(ValidateOrder);

    // now we fold (Aggregate) over the list of validated orders...
    // ...to collect all orders (or their concatenated errors) in a single FSharpChoice

    // we need first an empty list of orders in the domain of validation:
    FSharpChoice<FSharpList<Order>, Errors> zero = ListModule.Empty<Order>().PureValidate();

    // now the actual fold
    return validatedOrders
        .Aggregate(zero, 
            (FSharpChoice<FSharpList<Order>, Errors> e, FSharpChoice<Order, Errors> c) => 
                from a in e
                join b in c on 1 equals 1
                select a.Cons(b))

        // finally we need to upcast the list to match the return type
        .Select(x => (IEnumerable<Order>)x);
}

Just as before with the conditional validator, we can (and should) abstract this to a higher-order function, and then we can express ValidateOrders() as:

static Func<IEnumerable<Order>, FSharpChoice<IEnumerable<Order>, Errors>> ValidateOrders =
    EnumerableValidator<Order>(ValidateOrder);

Epilogue

Validating with applicative functors is nothing new. Haskell and Scala developers have been doing it for quite some time now.

This approach to validation is attractive because it's very simple. It all revolves around the FSharpChoice type which is one of the basic building blocks in functional programming, and a very simple type: it's either this or that, either the validated value or the list of errors.

There are no ad-hoc concepts about validation here: validators are functions returning FSharpChoice<T, Errors> . We use higher-order functions to abstract validators. Folding and mapping, to manipulate validations. Validators are composed through an applicative functor or monad. These are all very general concepts. Accidental difficulty (sometimes also called "accidental complexity") is low. The core that enables applicative functor validation can be expressed in around 30 lines of F# code. In contrast, commonly used validation libraries in .NET have lots of types representing non-generic, ad-hoc concepts, abstractions, with ad-hoc interactions. Therefore, concept count and accidental complexity are high. 

Of course, applicative functors are best expressed and understood in functional languages, but C# 3 seems to be a good enough vehicle for them. They can be expressed even in Java (the Functional Java library implements the validation applicative functor) although it's quite verbose. If you want to learn more about applicative functors, see:

If you found this post interesting, stay tuned: Steffen, Ryan and I are planning to create a general FP library for C# and F#, where this code would be part of said library, among many other things. In the meantime, you can find the code here.

Tuesday, February 8, 2011

Validation in formlets

Last time, we broke up formlets into primitive applicative functors, then composed these primitives to produce formlets.

So far, if someone entered an unexpected value in our little implementation of formlets (e.g. "abc" in an int Formlet), we'd get a nasty exception and there wasn't much we could do about it because we couldn't trace the exception to the formlet that was producing it. What we want, instead of an exception, is something that accumulates errors without interrupting the computation flow. Applicative functors, being oblivious, are perfect for that. More concretely, we want to:

  1. Know if the formlet was able to collect the value or not, and 
  2. if it couldn't, get the formlet rendered with the values the user entered and error messages, so we can re-display this second form, giving the user a chance to correct his mistakes.

The first item is a job for the option type. We'll return Some v if the formlet was successful and None if it wasn't.

For the second, we already have a XmlWriter applicative, so we could just reuse it to build this "error form".

Recall the type of formlets as we defined it last time:

type 'a Formlet = 'a Environ XmlWriter NameGen

Adding the two concerns we just mentioned, the signature becomes:

type 'a Formlet = 'a Error XmlWriter Environ XmlWriter NameGen

where Error is the Maybe monad in applicative form (remember that every monad is also an applicative functor).

This is what I was talking about when I mentioned formlets being extensible: you can extend formlet features by composing additional applicatives.

By the way, here's the same formlet type expressed using C# bracket style (which F# also supports):

type Formlet<'a> = NameGen<XmlWriter<Environ<XmlWriter<Error<'a>>>>>

See now why I prefer ML syntax? Bracket style looks quite messy once you start nesting many types.

Anyway, it's not enough to compose these applicatives, we also need some way to define how to validate things and how to show error messages. Let's define a validator type:

/// Validator type. 
/// Fst determines if value is valid 
/// Snd builds an error message 
type 'a Validator = ('a -> bool) * ('a -> xml_item list -> xml_item list)

and a function that attaches a validator to a formlet:

satisfies : 'a Validator -> 'a Formlet -> 'a Formlet

(I'm not going to bore you with implementation details in this post)
So we can now write:

let isInt = Int32.TryParse >> fst 
let intErrorMsg a xml = xml @ [ Tag("span", ["class","error"], [Text(sprintf "'%s' is not a valid number" a)]) ] 
let inputInt = input |> satisfies (isInt, intErrorMsg) |> lift int

When rendered the first time, this formlet doesn't show anything different:

printfn "%s" (render inputInt)

<input name="input_0" value=""/>

If we enter an invalid value, validation kicks in:

let env = EnvDict.fromValueSeq ["input_0","abc"] 
match run inputInt env with 
| _, Some v -> printfn "Formlet successful, value %d" v 
| errorForm, None -> printfn "Formlet unsuccessful, error form: \n%A" (XmlWriter.render errorForm)

This will print:

Formlet unsuccessful, error form: 
<div> 
    <input name="input_0" value="abc" /> 
    <span class="error">'abc' is not a valid number</span> 
</div>

We might want to wrap all that XML/HTML manipulation in order to make defining validators easier, for example:

/// <summary> 
/// Constructs a validator 
/// </summary> 
/// <param name="isValid">Determines if value is valid</param> 
/// <param name="errorMsg">Builds the error message</param> 
let err (isValid: 'a -> bool) (errorMsg: 'a -> string) : 'a Validator = 
    let addError value xml = 
        [ Tag("span", ["class","errorinput"], xml) 
          Tag("span", ["class","error"], [Text(errorMsg value)]) ]
    isValid, addError

Now we can code inputInt as:

let inputInt = input |> satisfies (err isInt (sprintf "'%s' is not a valid number")) |> lift int

We can chain as many validators as we want for any formlet. For example, here's a formlet that checks that the submitted value falls within a specified range:

let isInRange min max n = n >= min && n <= max
let inputRange min max = inputInt |> satisfies (err (isInRange min max) (fun _ -> sprintf "Value must be between %d and %d" min max))
let input10to40 = inputRange 10 40

Note how I used inputInt as the starting point for inputRange. inputInt is already validated for integers, so any non-integers values fed to inputRange will fail with the same error message as before. inputRange adds further validation on top of inputInt's validation. This is another example of the composability of formlets.

I put up a fully-fledged implementation of formlets, including validation, on github. There are some minor differences with what I've written so far about formlets. I'll blog about these differences soon.

As with all my previous articles on formlets, I have to give credit to the Links team; these blog posts and code are mostly just a rehash of their papers, which I can't recommend enough.

Tuesday, January 25, 2011

A factored implementation of formlets in F#

In my last post I showed a bare bones implementation of formlets. You may have noticed that formlets do a lot of stuff:

  • Generating form element names
  • Handling submitted values
  • Building and rendering HTML

That's a lot of responsibilities for a single module. Even the type of a formlet reflects this, it's pretty complex:

type 'a Formlet = int -> (xml_item list * ((string * string) list -> 'a) * int)

And we haven't even looked at adding validation, which would complicate things further. Bottom line: there is no clear separation of concerns.

The good news are: we already have identified those concerns (the bulleted list above), and applicative functors are easily composable, so we can model each of those concerns as independent applicative functors, then compose them to yield formlets.

HTML building

As usual, we start by defining types: the same definition for XML trees:

type xml_item =
    | Text of string
    | Tag of string * (string*string) list * xml_item list

And the type of the applicative functor itself:

type 'a XmlWriter = xml_item list * 'a

A XML forest and something else. That 'something else' is what will enable the composition of this applicative with others.

Finally, the implementation. If you compare this with the implementation of formlets described in the previous post, function by function, you'll see that this is effectively a stripped down applicative that only deals with XML.

module XmlWriter =
    let puree (v: 'a) : 'a XmlWriter = [],v
    let (<*>) (f: ('a -> 'b) XmlWriter) (a: 'a XmlWriter) : 'b XmlWriter =
        fst f @ fst a, (snd f) (snd a)
    let lift f a = puree f <*> a
    let lift2 f a b = puree f <*> a <*> b
    let plug (f: xml_item list -> xml_item list) (a: 'a XmlWriter) : 'a XmlWriter =
        f (fst a), snd a
    let xml (e: xml_item list): unit XmlWriter = e,()
    let text (s: string) : unit XmlWriter =
        xml [Text s]
    let tag (t: string) (attr: (string*string) list) (v: 'a XmlWriter) : 'a XmlWriter =
        plug (fun x -> [Tag(t, attr, x)]) v

    open System.Xml.Linq
    let render (xml: xml_item list) : XDocument =
        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

The only additional function here is plug, which maps the XML forest in a XmlWriter applicative. It's not of much use here and could be inlined, but it will be useful later to implement validation (in a future post).

Environment handling

The environment (or collector) applicative is one that fetches (collects) a value from the environment (usually Request.Form in ASP.NET). As such, its type is

type 'a Environ = (string*string) list -> 'a

The implementation:

module Environ =
    let puree v = fun env -> v
    let (<*>) (f: ('a -> 'b) Environ) (a: 'a Environ) : 'b Environ =
        fun env ->
            let g = f env
            g(a(env))
    let lift f a = puree f <*> a
    let lookup (n: string) : string Environ =
        fun env ->
            match List.tryFind (fun (k,_) -> k = n) env with
            | Some (_,v) -> v
            | _ -> failwithf "Key %s not found in environment" n

Note the lookup function, it's an Environ constructor that implements the core functionality of "given this key and this environment, give me the corresponding value". It's pretty much a dictionary in applicative form.

We'll also add here a helper function to convert a NameValueCollection (like Request.Form) to an environment:

    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

Name generation

We've seen how formlets automatically generate form element names. While the actual generation is provided by nextName, the counter used is carried over from application to application, since this is purely functional code, without state:

type 'a NameGen = int -> 'a * int
module NameGen =
    let puree (v : 'a) : 'a NameGen = 
        fun gen -> v,gen
    let (<*>) (f: ('a -> 'b) NameGen) (a: 'a NameGen) : 'b NameGen = 
        fun gen ->
            let v,gen = f gen
            let w,gen = a gen
            v w, gen
    let lift f a = puree f <*> a
    let lift2 f a b = puree f <*> a <*> b
    let nextName : string NameGen =
        fun gen ->
            "input_" + gen.ToString(), gen+1
    let run (c: 'a NameGen) : 'a = fst (c 0)

Here's a simple example of name generation:

> open NameGen;; 
> let names = puree (printfn "%s %s") <*> nextName <*> nextName;; 
> run names;; 
input_0 input_1

Composing applicatives

Applicative functors are easily composable, and the composition of any two applicatives is an applicative (math people say they're closed under composition). Interestingly, monads are not closed under composition, which as far as I understand is the reason for having monad transformers, but this doesn't seem to be a problem in F# since monads aren't as ubiquitous as in Haskell anyway.

Composing two applicatives is as simple as applying one applicative's pure to the other applicative's pure, and lifting <*>. Again, since we can't abstract type constructors, we can't perform composition generically, but we can always do it ad-hoc.

type 'a EnvironXmlWriter = 'a Environ XmlWriter

Expanding the types, this means

type 'a EnvironXmlWriter = xml_item list * ((string * string) list -> 'a)

The implementation:

module EnvironXmlWriter =
    let puree (v: 'a) : 'a Environ XmlWriter = 
        v |> Environ.puree |> XmlWriter.puree 
    let (<*>) (f: ('a -> 'b) Environ XmlWriter) (a: 'a Environ XmlWriter) : 'b Environ XmlWriter = 
        XmlWriter.lift2 Environ.(<*>) f a
    let lift f a = puree f <*> a

We'll also add a refine function that lets us build the composition from the "wrapping" applicative (in our case XmlWriter). Building it from the nested applicative is as easy as applying XmlWriter.pure.

    let refine (x: 'a XmlWriter) : 'a Environ XmlWriter =
        XmlWriter.lift Environ.puree x

Example:

let input : string Environ XmlWriter =  
    let xml = [Tag("input",["name","firstname"],[])] 
    let lookup = Environ.lookup "firstname"
    xml,lookup

This is almost a formlet. Just like a fully-fledged formlet, it has a XML part that can be rendered, and an associated collector. The only thing missing here is the automatic name generation applied to both the XML element and the collector.

Finally Formlets

All we have to do now is compose EnvironXmlWriter with NameGen to yield Formlets. Its type is:

type 'a Formlet = 'a EnvironXmlWriter NameGen

or

type 'a Formlet = 'a Environ XmlWriter NameGen

or if we expand each type:

type 'a Formlet = int -> (xml_item list * ((string * string) list -> 'a) * int)

which is exactly what we had in the last post. As you can see, factoring it to primitive applicatives has given us a clearer definition.

The implementation of formlets is almost trivial now:

module Formlet =
    let puree v : _ Formlet = v |> EnvironXmlWriter.puree |> NameGen.puree
    let (<*>) (f: ('a -> 'b) Formlet) (a: 'a Formlet) : 'b Formlet =
        NameGen.lift2 EnvironXmlWriter.(<*>) f a
    let lift f a : _ Formlet = 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
    let xml (x: xml_item list) : unit Formlet =
        NameGen.puree (EnvironXmlWriter.refine (XmlWriter.xml x))
    let text (s: string) : unit Formlet =
        xml [Text s]
    let tag (t: string) (attr: (string*string) list) (f: 'a Formlet) : 'a Formlet =
        NameGen.lift (XmlWriter.tag t attr) f
    let input : string Formlet =
        let xml name = XmlWriter.tag "input" ["name",name]
        let lookup name = XmlWriter.puree (Environ.lookup name)
        let tag name = xml name (lookup name)
        NameGen.lift tag NameGen.nextName
    let br: unit Formlet = xml [Tag("br",[],[])]
    let run (f: 'a Formlet) : 'a Environ =
        NameGen.run f |> snd

    open System.Xml.Linq
    let render (f: _ Formlet) = 
        NameGen.run f |> fst |> XmlWriter.render
F# Web Snippets

Factoring formlets like this not only has the advantage of producing cleaner code, but also enables the reusability of each applicative functor and extending formlets more easily, as we'll see in a future post.

Full source code is here. This implementation is interchangeable with the one in my last post, the project includes both implementations so you can compare them side by side. Most of this code was taken almost verbatim from the original papers on formlets.

namespace Formlets
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
val puree : 'a -> int -> 'a * int

Full name: Formlets.NameGen.puree
val v : 'a
type 'a NameGen = int -> 'a * int

Full name: Formlets.NameGen<_>
val gen : 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) NameGen
val a : 'a NameGen
val v : ('a -> 'b)
val w : 'a
val lift : ('a -> 'b) -> 'a NameGen -> 'b NameGen

Full name: Formlets.NameGen.lift
val f : ('a -> 'b)
val lift2 : ('a -> 'b -> 'c) -> 'a NameGen -> 'b NameGen -> 'c NameGen

Full name: Formlets.NameGen.lift2
val f : ('a -> 'b -> 'c)
val b : 'b NameGen
val nextName : int -> string * int

Full name: Formlets.NameGen.nextName
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>
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 run : 'a NameGen -> 'a

Full name: Formlets.NameGen.run
val c : 'a NameGen
val fst : ('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
type 'a Environ = (string * string) list -> 'a

Full name: Formlets.Environ<_>
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
val puree : 'a -> 'b -> 'a

Full name: Formlets.Environ.puree
val env : 'b
val f : ('a -> 'b) Environ
val a : 'a Environ
val env : (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 g : ('a -> 'b)
val lift : ('a -> 'b) -> 'a Environ -> 'b Environ

Full name: Formlets.Environ.lift
val lookup : string -> (string * string) list -> string

Full name: Formlets.Environ.lookup
val n : 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>
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 tryFind : ('T -> bool) -> 'T list -> 'T option

Full name: Microsoft.FSharp.Collections.List.tryFind
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>
union case Option.Some: 'T -> Option<'T>
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 failwithf : Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
namespace System
namespace System.Collections
namespace System.Collections.Specialized
val fromNV : NameValueCollection -> (string * string) list

Full name: Formlets.Environ.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 toList : seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
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
union case xml_item.Text: string -> xml_item
union case xml_item.Tag: string * (string * string) list * xml_item list -> xml_item
type 'a XmlWriter = xml_item list * 'a

Full name: Formlets.XmlWriter<_>
val puree : 'a -> 'a XmlWriter

Full name: Formlets.XmlWriter.puree
val f : ('a -> 'b) XmlWriter
val a : 'a XmlWriter
val snd : ('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val lift : ('a -> 'b) -> xml_item list * 'a -> 'b XmlWriter

Full name: Formlets.XmlWriter.lift
val lift2 : ('a -> 'b -> 'c) -> xml_item list * 'a -> xml_item list * 'b -> 'c XmlWriter

Full name: Formlets.XmlWriter.lift2
val b : 'b XmlWriter
val plug : (xml_item list -> xml_item list) -> xml_item list * 'a -> 'a XmlWriter

Full name: Formlets.XmlWriter.plug
val f : (xml_item list -> xml_item list)
val xml : xml_item list -> unit XmlWriter

Full name: Formlets.XmlWriter.xml
val e : 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 XmlWriter

Full name: Formlets.XmlWriter.text
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>
val tag : string -> (string * string) list -> xml_item list * 'a -> 'a XmlWriter

Full name: Formlets.XmlWriter.tag
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 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 v : 'a XmlWriter
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
namespace System.Xml
namespace System.Xml.Linq
val render : xml_item list -> XDocument

Full name: Formlets.XmlWriter.render
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
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)
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 * 'a -> XObject)
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 value : 'a
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 * 'a) list -> XObject list)
val attr : (string * 'a) list

  type: (string * 'a) list
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<List<string * 'a>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.Generic.IEnumerable<string * 'a>
  implements: System.Collections.IEnumerable
val map : ('T -> 'U) -> 'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val xelem : (string -> 'a list -> 'a list -> XObject)
val attr : 'a list

  type: 'a list
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<List<'a>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.Generic.IEnumerable<'a>
  implements: System.Collections.IEnumerable
val children : 'a list

  type: 'a list
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<List<'a>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.Generic.IEnumerable<'a>
  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
val puree : 'a -> 'a Environ XmlWriter

Full name: Formlets.EnvironXmlWriter.puree
Multiple items
module Environ

from Formlets

--------------------

type 'a Environ = (string * string) list -> 'a

Full name: Formlets.Environ<_>
Multiple items
module XmlWriter

from Formlets

--------------------

type 'a XmlWriter = xml_item list * 'a

Full name: Formlets.XmlWriter<_>
val f : ('a -> 'b) Environ XmlWriter
val a : 'a Environ XmlWriter
val lift : ('a -> 'b) -> xml_item list * 'a Environ -> 'b Environ XmlWriter

Full name: Formlets.EnvironXmlWriter.lift
val refine : xml_item list * 'a -> 'a Environ XmlWriter

Full name: Formlets.EnvironXmlWriter.refine
val x : 'a XmlWriter
type 'a Formlet = 'a Environ XmlWriter NameGen

Full name: Formlets.Formlet<_>
Multiple items
module NameGen

from Formlets

--------------------

type 'a NameGen = int -> 'a * int

Full name: Formlets.NameGen<_>
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
Multiple items
module Formlet

from Formlets

--------------------

type 'a Formlet = 'a Environ XmlWriter NameGen

Full name: Formlets.Formlet<_>
val puree : 'a -> 'a Formlet

Full name: Formlets.Formlet.puree
module EnvironXmlWriter

from Formlets
val f : ('a -> 'b) Formlet
val a : 'a Formlet
val lift : ('a -> 'b) -> 'a Formlet -> 'b Formlet

Full name: Formlets.Formlet.lift
val lift2 : ('a -> 'b -> 'c) -> 'a Formlet -> 'b Formlet -> 'c Formlet

Full name: Formlets.Formlet.lift2
val b : 'b Formlet
val f : 'a Formlet
val a : 'b Formlet
val z : 'b
val z : 'a
val xml : xml_item list -> unit Formlet

Full name: Formlets.Formlet.xml
val text : string -> unit Formlet

Full name: Formlets.Formlet.text
val tag : string -> (string * string) list -> 'a Formlet -> 'a Formlet

Full name: Formlets.Formlet.tag
val input : string Formlet

Full name: Formlets.Formlet.input
val xml : (string -> 'a XmlWriter -> 'a XmlWriter)
val lookup : (string -> string Environ XmlWriter)
val tag : (string -> string Environ XmlWriter)
val br : unit Formlet

Full name: Formlets.Formlet.br
val run : 'a Formlet -> 'a Environ

Full name: Formlets.Formlet.run
val render : 'a Formlet -> XDocument

Full name: Formlets.Formlet.render