monadic comprehensions and functional composition with query expressions

50
Monadic Comprehensions and Functional Composition with Query Expressions Chris Eargle

Upload: chris-eargle

Post on 10-May-2015

2.779 views

Category:

Technology


2 download

DESCRIPTION

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.

TRANSCRIPT

Page 1: Monadic Comprehensions and Functional Composition with Query Expressions

Monadic Comprehensions and Functional Composition with

Query Expressions

Chris Eargle

Page 2: Monadic Comprehensions and Functional Composition with Query Expressions

LINQ to Objects

Page 3: Monadic Comprehensions and Functional Composition with Query Expressions

Oh, that’s a monad!

Page 4: Monadic Comprehensions and Functional Composition with Query Expressions

List Monad

Page 5: Monadic Comprehensions and Functional Composition with Query Expressions

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)

Page 6: Monadic Comprehensions and Functional Composition with Query Expressions

Query Expressions

Page 7: Monadic Comprehensions and Functional Composition with Query Expressions

var words = new[] { "the", "quick", "brown", "fox"};

IEnumerable<string> query = from word in words select word;

Page 8: Monadic Comprehensions and Functional Composition with Query Expressions

var query = from word in words orderby word.Length select word;

Page 9: Monadic Comprehensions and Functional Composition with Query Expressions

var query = from word in words orderby word.Length select word.Replace(‘o’, ‘a’);

Page 10: Monadic Comprehensions and Functional Composition with Query Expressions

var query = words.OrderBy(w => w.Length) .Select(w => w.Replace('o', 'a'));

Page 11: Monadic Comprehensions and Functional Composition with Query Expressions

Monad

Page 12: Monadic Comprehensions and Functional Composition with Query Expressions

Functional Design Pattern

Page 13: Monadic Comprehensions and Functional Composition with Query Expressions

ReturnBind

Page 14: Monadic Comprehensions and Functional Composition with Query Expressions

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); } }

Page 15: Monadic Comprehensions and Functional Composition with Query Expressions

public static class Monad { public static Monad<T> Create<T>(T value) { return new Monad<T>(value); } }

Page 16: Monadic Comprehensions and Functional Composition with Query Expressions

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);

Page 17: Monadic Comprehensions and Functional Composition with Query Expressions

Identity Monad

Page 18: Monadic Comprehensions and Functional Composition with Query Expressions

public struct Identity<T> { T value; public T Value { get { return value; } } public Identity(T value) { this.value = value; } }

Page 19: Monadic Comprehensions and Functional Composition with Query Expressions

public static class Identity { public static Identity<T> Create<T>(T value) { return new Identity<T>(value); } }

Page 20: Monadic Comprehensions and Functional Composition with Query Expressions

var result = from x in Identity.Create(1) select x.ToString();

Assert.AreEqual("1", result.Value);

Page 21: Monadic Comprehensions and Functional Composition with Query Expressions

public Identity<TResult> Select<TResult>(Func<T, TResult> selector)

{ return Identity.Create(selector(value)); }

Page 22: Monadic Comprehensions and Functional Composition with Query Expressions

var result = from x in Identity.Create(2) from y in Identity.Create(3) select x + y;

Assert.AreEqual(5, result.Value);

Page 23: Monadic Comprehensions and Functional Composition with Query Expressions

public Identity<TResult> SelectMany<U, TResult>( Func<T, Identity<U>> selector, Func<T, U, TResult> resultSelector){ return Identity.Create(resultSelector(value,

selector(value).Value));}

Page 24: Monadic Comprehensions and Functional Composition with Query Expressions

var result = from x in Identity.Create(2) from y in Identity.Create(3) select x + y;

Assert.AreEqual(5, result.Value);

Page 25: Monadic Comprehensions and Functional Composition with Query Expressions

Cut the Middle Man

Page 26: Monadic Comprehensions and Functional Composition with Query Expressions

var result = from x in 2 from y in 3 select x + y;

Assert.AreEqual(5, result);

Page 27: Monadic Comprehensions and Functional Composition with Query Expressions

public static TResult SelectMany<T1, T2, TResult>( this T1 source, Func<T1, T2> selector, Func<T1, T2, TResult> resultSelector){ return resultSelector(source, selector(source));}

Page 28: Monadic Comprehensions and Functional Composition with Query Expressions

Tuples

Page 29: Monadic Comprehensions and Functional Composition with Query Expressions

var result = from info in ConferenceInfo() from dates in ConferenceDates() select new { Name = info.Item1, StartDate = dates.Item1, EndDate = dates.Item3 };

Page 30: Monadic Comprehensions and Functional Composition with Query Expressions

Assert.AreEqual("IEEE ICCSIT", result.Name);

Assert.AreEqual(july9th, result.StartDate);

Assert.AreEqual(july11th, result.EndDate);

Page 31: Monadic Comprehensions and Functional Composition with Query Expressions

Continuation Monad

Page 32: Monadic Comprehensions and Functional Composition with Query Expressions

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); }}

Page 33: Monadic Comprehensions and Functional Composition with Query Expressions

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); } }

Page 34: Monadic Comprehensions and Functional Composition with Query Expressions

public static Continuation<R, int> Square<R>(int x){ return Continuation.Create<R, int>(() => x * x);}

Page 35: Monadic Comprehensions and Functional Composition with Query Expressions

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);}

Page 36: Monadic Comprehensions and Functional Composition with Query Expressions

Assert.AreEqual(5, Hypotenuse<double>(3, 4).Run(n => n));

Page 37: Monadic Comprehensions and Functional Composition with Query Expressions

Cut the Middle Man

Page 38: Monadic Comprehensions and Functional Composition with Query Expressions

Func<int, int> square = x => x * x;Func<int, double> squareRoot = x => Math.Sqrt(x);

Page 39: Monadic Comprehensions and Functional Composition with Query Expressions

var hypotenuse = from h in square from w in square select squareRoot(h + w);

Assert.AreEqual(5, hypotenuse(3, 4));

Page 40: Monadic Comprehensions and Functional Composition with Query Expressions

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)); }

Page 41: Monadic Comprehensions and Functional Composition with Query Expressions

Func<int, int> f = x => x + 2;

var result = from x in f select x * 2;

Assert.AreEqual(6, result(1));

Page 42: Monadic Comprehensions and Functional Composition with Query Expressions

public static Func<T, TResult2> Select <T, TResult, TResult2>( this Func<T, TResult> func, Func<TResult, TResult2> selector) { return a => selector(func(a)); }

Page 43: Monadic Comprehensions and Functional Composition with Query Expressions
Page 44: Monadic Comprehensions and Functional Composition with Query Expressions

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; }; }

Page 45: Monadic Comprehensions and Functional Composition with Query Expressions

Factorial

Page 46: Monadic Comprehensions and Functional Composition with Query Expressions

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));

Page 47: Monadic Comprehensions and Functional Composition with Query Expressions

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; };}

Page 48: Monadic Comprehensions and Functional Composition with Query Expressions
Page 49: Monadic Comprehensions and Functional Composition with Query Expressions

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);

Page 50: Monadic Comprehensions and Functional Composition with Query Expressions

monadic.codeplex.com