May 04, 2014

How F Sharp Can Help With LINQ

I took a break from the web and decided to work on something different, like F#. What I didn’t realize is how awesome F# has helped me understand LINQ in C# and Vice Versa.

I have read most of the blog, from the Edulinq series. This gave me insight to what is happening in LINQ, it’s to crunch lists of data. This sounds like something that F# does well.

Some of the structure threw me off of F#, like loops and if/else statements. But there are ways around this:

Pattern Matching

In order to have a traditional switch statement, or if/else for that matter, you should look into pattern matching:

 match isDivisible with | true -> acc/item | false -> acc 

This show how to switch between true and false. Pattern matching is more powerful than switch statements, however:

 match list with | head -> (\* process one item \*) | tail -> (\* process the rest of the list \*) | \_ -> (\* oops something happened \*) 

So for the simple example, this is matching pieces of a list. The first line you process the first item in the list, and the second line, you process the rest of the list. This pattern can help process a list super quickly.

Fold and Unfold

So now that you have your branching methods, how can you loop and generate data? This is where [1 .. n] comes in. If you need to generate data, you can use this, but what if you need to generate a more complex set of data? Use an unfold:

 Seq.unfold( fun(x) -> Some(x, x+1) ) 2 |> Seq.takeWhile (fun x -> x = 10) 

The first line takes a function that generates a list from 2 to some number incrementing by 1. The second line stops generating numbers, once you get to 10. So after these 2 lines, it will generate an IEnumberable that will yield: [2,3,4,5,6,7,8,9,10]. It is important to note that this does not execute until you need to process the data later. Something we are fond of in LINQ with enumerables.

So this generates a list, how can we condense a list into one thing, like a Sum? Use a fold:

 [1..10] |> Seq.fold(fun acc elem -> acc = acc + elem) 0 

While you could use the Sum function, fold can do the same thing, and more. Fold takes in a set, [1..10], a function, and a starting value. The function has a signature of 2 parameters, the accumlator and each element it will loop through.

The neat thing with F# is that all Seq, or List or Array objects have these functions, more or less. All these functions do is loop through all the elements of a collection and execute the same function on each of the elements. The difference is what is returned from those values.

More useful list functions in F#

Filter

Filter is like a where clause in SQL. It filters stuff, daaa! Takes: a list, and a function that takes an element and returns a bool Returns: a list of items that fit that criteria

Map

Map executes a function on each item of an array. Note this may change the element

Takes: a list, and a function that executes on every item in the list

Returns: The modified list

Iter

Much like Map, except it does not return a modified list, and is more for side effects.

Takes: a list, and a function that executes on every item in the list

Returns: unit, which basically means returns nothing (not null, it’s complicated)

nth

Yes, there is a function called nth, which gives you that nth item, get it?

Takes: a list, and the index of the value you wanted

Returns: the element of that index. kinda like in c# array a[1] or elementAt

rev

Reverses an list

Takes: a list

Returns: the reverse of the list

max

Gets the max number

Takes: a list

Returns: the maximum value of the array

sum

Gets the sum of an list

Takes: a list

Returns: The sum of all the values

append

Smashes 2 arrays together

Takes: a list and another list

Returns: both lists put together

init

Creates a sequence, in case the [1..n] method doesn’t work. And for int64, it doesn’t

Takes: The number you want to count up to and a function to generate for each index

Returns: a list

These functions and techniques are the basics, and will help you write some F# that is useful. Not only that, I hope it helps give you a new perspective on LINQ, because they are basically the same thing. If you have an F#, or LINQ, function that is also useful, please throw them into the comments.