Last active
December 20, 2015 20:19
-
-
Save btawney/6189399 to your computer and use it in GitHub Desktop.
Functional lists and some higher order functions in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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