Doing Functional Programming in C# vs F# April, 2010
I wanted to use the F# unfold construct in some C# code today (.NET 3.5) and of course Linq doesn't offer an equivalent. So just for fun I thought I'd hand craft what was needed to do it in C# (I know this has been done before, nothing new):
public static class Functional { public static class Seq { public static IEnumerable<T> Unfold<T,TState>(Func<TState, Tuple<T, Option<TState>>> generator, TState state) { TState currentState = state; while (true) { Tuple<T, Option<TState>> result = generator(currentState); if (result.Value2.State == Option<TState>.OptionState.None) break; currentState = result.Value2.Value; yield return result.Value1; } } } public class Tuple<T1, T2> { private Tuple(T1 value1, T2 value2) { Value1 = value1; Value2 = value2; } public static Tuple<T1, T2> Create(T1 value1) { return new Tuple<T1, T2>(value1, default(T2)); } public static Tuple<T1, T2> Create(T2 value2) { return new Tuple<T1, T2>(default(T1), value2); } public static Tuple<T1, T2> Create(T1 value1, T2 value2) { return new Tuple<T1, T2>(value1, value2); } public T1 Value1 { get; private set; } public T2 Value2 { get; private set; } } public class Option<T> { public enum OptionState { Some, None } private Option() { State = OptionState.None; } private Option(T value) { State = OptionState.Some; Value = value; } public static Option<T> None() { return new Option<T>(); } public static Option<T> Some(T value) { return new Option<T>(value); } public OptionState State { get; private set; } public T Value { get; private set; } } }
Let's see how this is defined in F# (From the source, pre .NET 4.0 tuple definition):
let unfold f x : IEnumerator<_> = let state = ref x upcast { new MapEnumerator<_>() with member this.DoMoveNext curr = match f !state with | None -> false | Some(r,s) -> curr <- r state := s true member this.Dispose() = () }
type Option<'T> = | None : 'T option | Some : Value:'T -> 'T option member x.Value = match x with Some x -> x | None -> raise (new System.InvalidOperationException("Option.Value")) member x.IsNone = match x with None -> true | _ -> false member x.IsSome = match x with Some _ -> true | _ -> false static member None : 'T option = None static member Some(x) : 'T option = Some(x) override x.ToString() = "Some("^anyToStringShowingNull x.Value^")" and 'T option = Option<'T>
[<Struct>] type Tuple<'T1,'T2> = new (v1,v2) = { Item1 = v1; Item2 = v2 } val Item1 : 'T1 val Item2 : 'T2
Discriminated unions and tuples are a language feature (Not just a type in the BCL as with tuples in 4.0). F# is nice and terse, much less "noise", esp. with type inference and the light syntax.
Here is the usage, and what really makes a big difference for me. C#:
var result = Functional.Seq.Unfold(state => gimmie(state) == null ? Functional.Tuple<string, Functional.Option<int>>.Create(Functional.Option<int>.None()) : Functional.Tuple<string, Functional.Option<int>>.Create(gimmie(state), Functional.Option<int>.Some(state + 1)), 0);
F#:
let result = Seq.unfold (fun state -> if (gimmie state) = null then None else Some(gimmie state, state + 1)) 0
Now I'm sure we can optimize and clean up the C# to be even terser (I'm sure my C# is a bit biased because I'm trying to make a point :) but the type inference and discriminated unions & tuples as a language feature make a huge difference. People often ask "what can I do in F# that I cant in C#?". And at first I had a hard time answering that question (Esp. with all the functional language features and constructs in C#/.NET these days). But the big difference is not necessarily what you can/cant do per se, but how easily and naturally you can do it. Functional programming is just much simpler and natural in F# because, well, its a functional language and therefore fully embraces the functional paradigm. In C#, which obviously is an imperative/OO language, you have to struggle to accomplish the same things you can naturally do in F#, and they can end up pretty ugly.