F# Object Tree Syntax

101 Views Asked by At

In C# it is possible to construct object trees in a rather succint syntax:

var button = new Button() { Content = "Foo" };

Is there an idiomatic way to do something similar in F#?

Records have nice syntax:

let button = { Content = "Foo" }

Object construction would appear to be a different matter, as far as I can tell. Normally I would write code such as:

let button = new Button()
button.Content <- "Foo"

Or even:

let button =
    let x = new Button()
    x.Content <- "Foo"
    x

One way to solve the problem is to use a custom fluent composition operator:

// Helper that makes fluent-style possible
let inline (.&) (value : 'T) (init: 'T -> unit) : 'T =
    init value
    value

let button = new Button() .& (fun x -> x.Content <- "Foo")

Is there built-in syntax to achieve this - or another recommended approach?

2

There are 2 best solutions below

3
Brian Berns On BEST ANSWER

F# lets you set properties right in the constructor call, so I think this should work for you:

let button = Button(Content = "Foo")
1
Romain Deneau On

In C#, this nice syntax is called object initializer and then the () can be removed (1). To change an object "inline" (fluent style) after its initialization, I like to have a With() extension method similar to your .& operator (2):

var button = new Button { Content = "Foo" }; // (1)

// (2)
public static T With<T>(this T @this, Action<T> update)
{
    change(@this);
    return @this;
}

var button2 = button.With(x => x.Content = "Bar")

In F#, for those who prefer piping instead of operator, the function can be named tap (see RxJs) or tee (by Scott Wlaschin here):

// f: ('a -> 'b) -> x: 'a -> 'a
let inline tee f x =
    f x |> ignore
    x

let button =
    Button(Content = "Foo")
    |> tee (fun x -> x.Color <- Blue)
    |> tee (fun x -> x.Content <- "Bar")

Related Questions in F#