Last night, I had to filter a bunch of entries in a sequence down to only those items that had a particular characteristic. My thought process went like this: “I have a list of objects. When I’m done, I want a list of objects that have property X, discarding everything else. Ah-ha, I want to fold the sequence into a List.” I had some other constraints, such as the other library I was using was written in C# and used List<T> instead of F# types. I don’t know that this is the best way to do things, but I’ll show it anyhow as an illustration of nifty stuff I’ve done lately.
The code takes an array of some well-defined type and then filters on that type. In this case, the type has a formalized string * int tuple with names to make it useful from C#. You can place any well defined C# data type in place to get equivalent effects. For example, imagine sorting some Person or Order business object in your F# code looking for People named Fred or Orders over $100. In our case, we have the type MyType as a stand-in. The code filters on the quality of the object and returns only those instances with that quality.
#light
open System.Collections.Generic
type MyType(propA:string, propB:int) =
member this.PropA = propA
member this.PropB = propB
override this.ToString() = System.String.Format("{0} {1}", this.PropA, this.PropB)
let typeSeq =
[| new MyType("red", 4);
new MyType("red", 3);
new MyType("blue", 3);
new MyType("blue", 4);
new MyType("blue", 5);
|]
let filterVals theSeq propAValue =
theSeq |> Seq.fold(fun (acc:List<MyType>) (a:MyType) ->
if (a.PropA = propAValue) then
acc.Add(a)
acc) (new List<MyType>())
printfn("%A") (filterVals typeSeq "red")
printfn("%A") (filterVals typeSeq "blue")
This code generates the following output in the interactive window:
seq [red 4; red 3]
seq [blue 3; blue 4; blue 5]
I like this syntax bit better than the LINQ syntax as I can achieve a typed collection in a trivial manner. I’m also enjoying the notion of moving away from explicit looping constructs and towards simple functions that just do the right thing for me.