Skip to content

Instantly share code, notes, and snippets.

@btawney
Last active December 20, 2015 20:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save btawney/6189399 to your computer and use it in GitHub Desktop.
Save btawney/6189399 to your computer and use it in GitHub Desktop.
Functional lists and some higher order functions in C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FunctionalTypes
{
public static class FunctionalList
{
public static FunctionalList<char> FromString(string s)
{
return new FunctionalList<char>(s.Length, x => s[x]);
}
public static FunctionalList<int> Series(int first, int last)
{
return new FunctionalList<int>(last - first + 1, x => x + first);
}
public static FunctionalList<int> Series(int first, int second, int last)
{
int difference = second - first;
int length = (last - first) / difference + 1;
return new FunctionalList<int>(length, x => x * difference + first);
}
}
public class FunctionalList<T>
{
public delegate T IndexFunction(int index);
private IndexFunction _function;
public IndexFunction Function
{
get
{
return this._function;
}
set
{
}
}
private int _length;
private bool _isInfinite;
public int Length
{
get
{
return this._length;
}
set
{
}
}
public bool IsInfinite
{
get
{
return this._isInfinite;
}
set
{
}
}
public FunctionalList(IndexFunction function)
{
this._function = function;
this._isInfinite = true;
}
public FunctionalList(int length, IndexFunction function)
{
this._function = function;
this._isInfinite = false;
this._length = length;
}
public T this[int index]
{
get
{
if (this._isInfinite == false && index >= this._length)
{
throw new IndexOutOfRangeException();
}
return this.Function(index);
}
set
{
}
}
public T Head
{
get
{
return this[0];
}
set
{
}
}
public FunctionalList<T> Take(int number)
{
return new FunctionalList<T>(number, this._function);
}
public FunctionalList<T> Take(int from, int length)
{
return new FunctionalList<T>(length, x => this._function(x + from));
}
public FunctionalList<T> Skip(int number)
{
if (this._isInfinite)
{
return new FunctionalList<T>(x => this._function(x + number));
}
else
{
return new FunctionalList<T>(this._length - number, x => this._function(x + number));
}
}
public FunctionalList<T> Tail
{
get
{
if (this._isInfinite)
{
return new FunctionalList<T>(x => this._function(x + 1));
}
else
{
return new FunctionalList<T>(this._length - 1, x => this._function(x + 1));
}
}
set
{
}
}
public FunctionalList<T> Append(FunctionalList<T> tail)
{
if (this._isInfinite)
{
return this;
}
if (tail._isInfinite)
{
return new FunctionalList<T>(x => x < this._length ? this[x] : tail[x + this._length]);
}
else
{
return new FunctionalList<T>(this._length + tail._length, x => x < this._length ? this[x] : tail[x + this._length]);
}
}
public FunctionalList<T> Construct(T head)
{
if (this._isInfinite)
{
return new FunctionalList<T>(x => x == 0 ? head : this[x - 1]);
}
else
{
return new FunctionalList<T>(this._length + 1, x => x == 0 ? head : this[x - 1]);
}
}
public override string ToString()
{
StringBuilder s = new StringBuilder();
int length = this._length;
if (this._isInfinite)
{
length = 100;
}
if (typeof(T) == typeof(char))
{
for (int i = 0; i < length; ++i)
{
s.Append(this[i]);
}
}
else
{
s.Append('[');
if (typeof(T) == typeof(string))
{
for (int i = 0; i < length; ++i)
{
if (i > 0)
{
s.Append(", ");
}
s.Append('"');
s.Append(this[i]);
s.Append('"');
}
}
else
{
for (int i = 0; i < length; ++i)
{
if (i > 0)
{
s.Append(", ");
}
s.Append(this[i]);
}
}
if (this._isInfinite)
{
s.Append("...");
}
s.Append(']');
}
return s.ToString();
}
public List<T> ToList()
{
if (this._isInfinite)
{
throw new Exception("Attempt to convert infinite functional array to a list");
}
List<T> newList = new List<T>();
for (int i = 0; i < this._length; ++i)
{
newList.Add(this[i]);
}
return newList;
}
public T[] ToArray()
{
if (this._isInfinite)
{
throw new Exception("Attempt to convert infinite functional array to a static array");
}
T[] newArray = new T[this._length];
for (int i = 0; i < this._length; ++i)
{
newArray[i] = this[i];
}
return newArray;
}
}
public class HigherOrderFunction<T1, TReturn>
{
public delegate TReturn MapFunction(T1 t1);
public static FunctionalList<TReturn> Map(MapFunction function, FunctionalList<T1> underlying)
{
if (underlying.IsInfinite)
{
return new FunctionalList<TReturn>(x => function(underlying[x]));
}
else
{
return new FunctionalList<TReturn>(underlying.Length, x => function(underlying[x]));
}
}
public delegate TReturn FoldLeftFunction(TReturn left, T1 right);
public static TReturn FoldLeft(FoldLeftFunction function, TReturn initial, FunctionalList<T1> underlying)
{
TReturn result = initial;
if (underlying.IsInfinite)
{
throw new Exception("Attempt to fold over an infinite array");
}
for (int i = 0; i < underlying.Length; ++i)
{
result = function(result, underlying[i]);
}
return result;
}
public delegate TReturn FoldRightFunction(T1 left, TReturn right);
public static TReturn FoldRight(FoldRightFunction function, TReturn initial, FunctionalList<T1> underlying)
{
TReturn result = initial;
if (underlying.IsInfinite)
{
throw new Exception("Attempt to fold over an infinite array");
}
for (int i = 0; i < underlying.Length; ++i)
{
result = function(underlying[i], result);
}
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment