Click here to Skip to main content
15,886,137 members
Articles / Programming Languages / F#

Tracking Dependencies and Side-Effects Using Immutability

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
7 Jul 2009CPOL7 min read 29.4K   50   7  
The Functional Programming for the Real World book explains essential concepts of the functional programming paradigm using examples in C# 3.0 and F#. In this article we look at one very important advantage of using one of the core functional concepts - immutability.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FunctionalCSharp
{
	// --------------------------------------------------------------------------
	// Functional Programming in .NET - Chapter 3, 5 and 6
	// --------------------------------------------------------------------------
	// NOTE: This library contains several useful classes for functional 
	// programming in C# that we implemented in chapters 3, 5 and 6 and that we'll 
	// extend and use later in the book. Each secion is marked with a reference
	// to a code listing or section in the book where it was discussed.
	// --------------------------------------------------------------------------

	// --------------------------------------------------------------------------
	// Section 3.3.3: Functional lists in C#

	// Listing 3.14 Functional list in C#

	/// <summary>
	/// Represents a functional list that can be eihter 
	/// 'empty list' or a 'cons cell'
	/// </summary>
	public class FuncList<T> : IEnumerable<T>
	{
		/// <summary>
		/// Constructor that creates an empty list
		/// </summary>
		public FuncList()
		{
			IsEmpty = true;
		}

		/// <summary>
		/// Constructor that creates a cons cell with an element 
		/// (head) and a reference to the rest of the list (tail)
		/// </summary>
		/// <param name="head">The elemnet stored by the cons cell</param>
		/// <param name="tail">Reference to the rest of the list</param>
		public FuncList(T head, FuncList<T> tail)
		{
			IsEmpty = false;
			Head = head;
			Tail = tail;
		}

		/// <summary>
		/// Is the list empty list or a cons cell?
		/// </summary>
		public bool IsEmpty { get; private set; }

		/// <summary>
		/// Returns the element stored in the cons cell
		/// </summary>
		public T Head { get; private set; }

		/// <summary>
		/// Returns reference to the rest of the list when the list is a cons cell
		/// </summary>
		public FuncList<T> Tail { get; private set; }

		public int Count
		{
			get { return IsEmpty ? 0 : (Tail.Count + 1); }
		}


		// Implementation of IEnumerable - Added in chapter 11

		public IEnumerator<T> GetEnumerator()
		{
			FuncList<T> el = this;
			while (!el.IsEmpty)
			{
				yield return el.Head;
				el = el.Tail;
			}
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}

	/// <summary>
	/// Utility class for constructing lists
	/// </summary>
	public static class FuncList
	{
		/// <summary>
		/// Creates an empty list
		/// </summary>
		public static FuncList<T> Empty<T>()
		{
			return new FuncList<T>();
		}

		/// <summary>
		/// Creates a cons cell storing an element of the list.
		/// This method can be used without specifying generic 
		/// type parameters thanks to the C# type inference.
		/// </summary>
		public static FuncList<T> Cons<T>(T head, FuncList<T> tail)
		{
			return new FuncList<T>(head, tail);
		}

		public static void Iter<T>(this FuncList<T> source, Action<T> f)
		{
			if (!source.IsEmpty) {
				f(source.Head);
				Iter(source.Tail, f);
			}
		}

    public static FuncList<T> Where<T>(this FuncList<T> source, Func<T, bool> f)
    {
      if (source.IsEmpty)
        return FuncList.Empty<T>();
      else {
        var rest = Where(source.Tail, f);
        return f(source.Head) ? FuncList.Cons(source.Head, rest) : rest;
      }
    }

		public static FuncList<R> Select<T, R>(this FuncList<T> source, Func<T, R> f)
		{
			if (source.IsEmpty)
				return FuncList.Empty<R>();
			else
				return FuncList.Cons(f(source.Head), Select(source.Tail, f));
		}

		private static FuncList<R> SelectUtil<T, R>(this FuncList<T> source, int i, Func<T, int, R> f)
		{
			if (source.IsEmpty)
				return FuncList.Empty<R>();
			else
				return FuncList.Cons(f(source.Head, i), SelectUtil(source.Tail, i + 1, f));
		}

		public static FuncList<R> Select<T, R>(this FuncList<T> source, Func<T, int, R> f)
		{
			return SelectUtil(source, 0, f);
		}

		public static FuncList<T> Concat<T>(this FuncList<FuncList<T>> concat)
		{
			var el = concat;
			List<T> elements = new List<T>();
			while (!el.IsEmpty)
			{
				var nested = el.Head;
				while (!nested.IsEmpty)
				{
					elements.Add(nested.Head);
					nested = nested.Tail;
				}
				el = el.Tail;
			}

			FuncList<T> ret = FuncList.Empty<T>();
			for (int i = 0; i < elements.Count; i++)
				ret = FuncList.Cons(elements[i], ret);
			return ret;
		}

		public static FuncList<T> ToFuncList<T>(this IEnumerable<T> seq)
		{
			FuncList<T> ret = FuncList.Empty<T>();
			foreach (var el in seq.Reverse())
				ret = FuncList.Cons(el, ret);
			return ret;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Czech Republic Czech Republic
I live in Prague, the capital city of Czech republic (most of the time Smile | :) ). I've been very interested in functional programming recently and I have a passion for the new Microsoft F# language. I'm writing a book about Functional Programming in the Real World that shows the ideas using examples in C# 3.0 and F#.

I've been Microsoft MVP (for C#) since 2004 and I'm one of the most active members of the F# community. I'm a computer science student at Charles University of Prague. My hobbies include photography, fractals and of course many things related to computers (except fixing them). My favorite book writers are Terry Pratchett and Philip K Dick and I like paintings by M. C. Escher.

PS: My favorite codeproject icon is Sheep | [baah] .

Comments and Discussions