Monadic Comprehensions and Functional Composition with Query Expressions
-
Upload
chris-eargle -
Category
Technology
-
view
2.777 -
download
2
description
Transcript of Monadic Comprehensions and Functional Composition with Query Expressions
Monadic Comprehensions and Functional Composition with
Query Expressions
Chris Eargle
LINQ to Objects
Oh, that’s a monad!
List Monad
LINQ to Objectsfrom x in new[] {1, 2, 3}from y in new[] {1, 2, 3}select Tuple.Create(x, y)
List Monaddo x <- [1,2,3] y <- [1,2,3] return (x,y)
Query Expressions
var words = new[] { "the", "quick", "brown", "fox"};
IEnumerable<string> query = from word in words select word;
var query = from word in words orderby word.Length select word;
var query = from word in words orderby word.Length select word.Replace(‘o’, ‘a’);
var query = words.OrderBy(w => w.Length) .Select(w => w.Replace('o', 'a'));
Monad
Functional Design Pattern
ReturnBind
public struct Monad<T> { private T value;
public Monad(T value) { this.value = value; }
public Monad<U> Bind<U>(Func<T, Monad<U>> func) { return func(value); } }
public static class Monad { public static Monad<T> Create<T>(T value) { return new Monad<T>(value); } }
var monad = Monad.Create(1);var monad2 = monad.Bind(v => Monad.Create(v));
Assert.IsInstanceOfType(monad, typeof(Monad<int>));Assert.AreEqual(monad, monad2);Assert.AreNotSame(monad, monad2);
Identity Monad
public struct Identity<T> { T value; public T Value { get { return value; } } public Identity(T value) { this.value = value; } }
public static class Identity { public static Identity<T> Create<T>(T value) { return new Identity<T>(value); } }
var result = from x in Identity.Create(1) select x.ToString();
Assert.AreEqual("1", result.Value);
public Identity<TResult> Select<TResult>(Func<T, TResult> selector)
{ return Identity.Create(selector(value)); }
var result = from x in Identity.Create(2) from y in Identity.Create(3) select x + y;
Assert.AreEqual(5, result.Value);
public Identity<TResult> SelectMany<U, TResult>( Func<T, Identity<U>> selector, Func<T, U, TResult> resultSelector){ return Identity.Create(resultSelector(value,
selector(value).Value));}
var result = from x in Identity.Create(2) from y in Identity.Create(3) select x + y;
Assert.AreEqual(5, result.Value);
Cut the Middle Man
var result = from x in 2 from y in 3 select x + y;
Assert.AreEqual(5, result);
public static TResult SelectMany<T1, T2, TResult>( this T1 source, Func<T1, T2> selector, Func<T1, T2, TResult> resultSelector){ return resultSelector(source, selector(source));}
Tuples
var result = from info in ConferenceInfo() from dates in ConferenceDates() select new { Name = info.Item1, StartDate = dates.Item1, EndDate = dates.Item3 };
Assert.AreEqual("IEEE ICCSIT", result.Name);
Assert.AreEqual(july9th, result.StartDate);
Assert.AreEqual(july11th, result.EndDate);
Continuation Monad
public class Continuation<R, A> { private readonly Func<Func<A, R>, R> value; internal Continuation(Func<Func<A, R>, R> func) { this.value = func; } public R Run(Func<A, R> k) { return value(k); }}
public static class Continuation { public static Continuation<R, A> Create<R, A>(Func<A> func) { return Continuation.Create<R, A>(k => k(func())); } public static Continuation<R, A> Create<R, A>(Func<Func<A, R>, R> func) { return new Continuation<R, A>(func); } }
public static Continuation<R, int> Square<R>(int x){ return Continuation.Create<R, int>(() => x * x);}
public static Continuation<R, double> Hypotenuse<R>(int x, int y)
{ return from h in Square<R>(x) from w in Square<R>(y) select Math.Sqrt(h + w);}
Assert.AreEqual(5, Hypotenuse<double>(3, 4).Run(n => n));
Cut the Middle Man
Func<int, int> square = x => x * x;Func<int, double> squareRoot = x => Math.Sqrt(x);
var hypotenuse = from h in square from w in square select squareRoot(h + w);
Assert.AreEqual(5, hypotenuse(3, 4));
public static Func<T1, T2, TResult3>SelectMany<T1, T2, TResult, TResult2, TResult3>( this Func<T1, TResult> leftFunc, Func<T1, Func<T2, TResult2>> rightFunc, Func<TResult, TResult2, TResult3> selector) { return (x, y) => selector(leftFunc(x), rightFunc(x)(y)); }
Func<int, int> f = x => x + 2;
var result = from x in f select x * 2;
Assert.AreEqual(6, result(1));
public static Func<T, TResult2> Select <T, TResult, TResult2>( this Func<T, TResult> func, Func<TResult, TResult2> selector) { return a => selector(func(a)); }
public static Func<Int32, Double> Sum(this Func<Int32, Double> func, int start = 0) { return end => { Double result = default(Double); for (int k = start; k <= end; k++) { result += func(k); } return result; }; }
Factorial
Func<int, int> f = x => x;
var factorial = from x in f.Sum() where x != 0 select x ?? 1;
Assert.AreEqual(1, factorial(0)); Assert.AreEqual(6, factorial(3));
public static Func<T, dynamic> Where<T, TResult>( this Func<T, TResult> func, Func<TResult, bool> predicate){ return a => { TResult result = func(a); return predicate(result) ? result as dynamic : null; };}
Func<Int32, Double> f = k => 4 * Math.Pow(-1, k) / (2.0 * k + 1); var calculatePi = f.Sum(); Assert.AreEqual(3.14159, calculatePi(200000), 7);
monadic.codeplex.com