Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Monadic Comprehensions and Functional Composition with Query Expressions

3,129 views

Published on

Build monads using the C# language with a C# style, then use the appropriate methods to ensure the LINQ query syntax works with this functional design pattern. After describing monads, we will cut the middleman and apply the same techniques directly to objects and functions to achieve better results with a declarative syntax.

Published in: Technology, Education, Business
  • Be the first to comment

Monadic Comprehensions and Functional Composition with Query Expressions

  1. 1. Monadic Comprehensions and Functional Composition with Query Expressions<br />Chris Eargle<br />
  2. 2. LINQ to Objects<br />
  3. 3. Oh, that’s a monad!<br />
  4. 4. List Monad<br />
  5. 5. LINQ to Objects<br />from x in new[] {1, 2, 3}from y in new[] {1, 2, 3}select Tuple.Create(x, y)<br />List Monad<br />do x <- [1,2,3]    y <- [1,2,3]    return (x,y)<br />
  6. 6. Query Expressions<br />
  7. 7. var words = new[] { "the", "quick", "brown", "fox"};<br />IEnumerable<string> query = from word in words<br /> select word;<br />
  8. 8. var query = from word in words<br />orderbyword.Length<br />select word;<br />
  9. 9. var query = from word in words<br />orderbyword.Length<br />select word.Replace(‘o’, ‘a’);<br />
  10. 10. var query = words.OrderBy(w => w.Length)<br /> .Select(w => w.Replace('o', 'a'));<br />
  11. 11. Monad<br />
  12. 12. Functional Design Pattern<br />
  13. 13. Return<br />Bind<br />
  14. 14. public struct Monad<T><br />{<br /> private T value;<br /> public Monad(T value)<br /> {<br />this.value = value;<br /> }<br /> public Monad<U> Bind<U>(Func<T, Monad<U>> func)<br /> {<br /> return func(value);<br /> }<br />}<br />
  15. 15. public static class Monad<br />{<br /> public static Monad<T> Create<T>(T value)<br /> {<br /> return new Monad<T>(value);<br /> }<br />}<br />
  16. 16. varmonad = Monad.Create(1);<br />varmonad2 = monad.Bind(v => Monad.Create(v));<br />Assert.IsInstanceOfType(monad, typeof(Monad<int>));<br />Assert.AreEqual(monad, monad2);<br />Assert.AreNotSame(monad, monad2);<br />
  17. 17. Identity Monad<br />
  18. 18. public struct Identity<T><br />{ <br /> T value;<br /> public T Value { get { return value; } }<br /> public Identity(T value)<br /> {<br />this.value = value;<br />}<br /> }<br />
  19. 19. public static class Identity<br /> {<br /> public static Identity<T> Create<T>(T value)<br /> {<br /> return new Identity<T>(value);<br /> }<br /> }<br />
  20. 20. varresult = from x in Identity.Create(1)<br />select x.ToString();<br />Assert.AreEqual("1", result.Value);<br />
  21. 21. public Identity<TResult> Select<TResult><br /> (Func<T, TResult> selector)<br />{<br />return Identity.Create(selector(value));<br />}<br />
  22. 22. var result = from x in Identity.Create(2)<br />from y in Identity.Create(3)<br /> select x + y;<br />Assert.AreEqual(5, result.Value);<br />
  23. 23. public Identity<TResult> SelectMany<U, TResult>(<br />Func<T, Identity<U>> selector, <br />Func<T, U, TResult> resultSelector)<br />{<br /> return Identity.Create(resultSelector(value, selector(value).Value));<br />}<br />
  24. 24. var result = from x in Identity.Create(2)<br />from y in Identity.Create(3)<br /> select x + y;<br />Assert.AreEqual(5, result.Value);<br />
  25. 25. Cut the Middle Man<br />
  26. 26. var result = from x in 2<br /> from y in 3<br /> select x + y;<br />Assert.AreEqual(5, result);<br />
  27. 27. public static TResultSelectMany<T1, T2, TResult>(<br /> this T1 source, <br />Func<T1, T2> selector, <br />Func<T1, T2, TResult> resultSelector)<br />{<br /> return resultSelector(source, selector(source));<br />}<br />
  28. 28. Tuples<br />
  29. 29. var result = from info in ConferenceInfo()<br />from dates in ConferenceDates()<br />select new<br />{<br /> Name = info.Item1,<br />StartDate = dates.Item1,<br />EndDate = dates.Item3<br />};<br />
  30. 30. Assert.AreEqual("IEEE ICCSIT", result.Name);<br />Assert.AreEqual(july9th, result.StartDate);<br />Assert.AreEqual(july11th, result.EndDate);<br />
  31. 31. Continuation Monad<br />
  32. 32. public class Continuation<R, A><br />{<br /> private readonlyFunc<Func<A, R>, R> value;<br /> internal Continuation(Func<Func<A, R>, R> func)<br /> {<br />this.value = func;<br />}<br /> public R Run(Func<A, R> k)<br /> {<br /> return value(k);<br />}<br />}<br />
  33. 33. public static class Continuation<br /> {<br /> public static Continuation<R, A> Create<R, A>(Func<A> func)<br /> {<br /> return Continuation.Create<R, A>(k => k(func()));<br />}<br /> public static Continuation<R, A> Create<R, A>(Func<Func<A, R>, R> func)<br /> {<br /> return new Continuation<R, A>(func);<br /> }<br /> }<br />
  34. 34. public static Continuation<R, int> Square<R>(int x){ return Continuation.Create<R, int>(() => x * x);}<br />
  35. 35. public static Continuation<R, double> Hypotenuse<R><br /> (int x, int y){ return from h in Square<R>(x)<br /> from w in Square<R>(y)<br /> select Math.Sqrt(h + w);}<br />
  36. 36. Assert.AreEqual(5, Hypotenuse<double>(3, 4).Run(n => n));<br />
  37. 37. Cut the Middle Man<br />
  38. 38. Func<int, int> square = x => x * x;<br />Func<int, double> squareRoot = x => Math.Sqrt(x);<br />
  39. 39. varhypotenuse = from h in square<br />from w in square<br />select squareRoot(h + w);<br />Assert.AreEqual(5, hypotenuse(3, 4));<br />
  40. 40. 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)<br /> {<br /> return (x, y) => selector(leftFunc(x), rightFunc(x)(y));<br /> }<br />
  41. 41. Func<int, int> f = x => x + 2;<br />var result = from x in f<br /> select x * 2;<br />Assert.AreEqual(6, result(1));<br />
  42. 42. public static Func<T, TResult2> Select <T, TResult, TResult2>( this Func<T, TResult> func, Func<TResult, TResult2> selector)<br /> {<br /> return a => selector(func(a));<br /> }<br />
  43. 43. f<br /> <br />
  44. 44. public static Func<Int32, Double> Sum(this Func<Int32, Double> func, intstart = 0)<br /> {<br /> return end =><br /> {<br /> Double result = default(Double);<br /> for (int k = start; k <= end; k++)<br /> {<br /> result += func(k);<br />}<br /> return result;<br /> };<br /> }<br />
  45. 45. Factorial<br />
  46. 46. Func<int, int> f = x => x;<br />varfactorial = from x in f.Sum()<br /> where x != 0<br /> select x ?? 1;<br />Assert.AreEqual(1, factorial(0));<br />Assert.AreEqual(6, factorial(3));<br />
  47. 47. public static Func<T, dynamic> Where<T, TResult>(<br /> this Func<T, TResult> func, <br />Func<TResult, bool> predicate)<br />{<br />return a =><br />{<br />TResult result = func(a);<br /> return predicate(result) ? result as dynamic : null;<br />};<br />}<br />
  48. 48. 4k=0∞−1k2k+1<br /> <br />
  49. 49. Func<Int32, Double> f = k => 4 * Math.Pow(-1, k) / (2.0 * k + 1);<br />varcalculatePi = f.Sum();<br />Assert.AreEqual(3.14159, calculatePi(200000), 7);<br />
  50. 50. monadic.codeplex.com<br />

×