using System.Threading.Tasks;
public static void Main()
var taskCreator = new TaskCreator();
Console.WriteLine("Before Expression");
from a in taskCreator.CreateTask1()
from b in taskCreator.CreateTask2()
from c in taskCreator.CreateTask3()
Console.WriteLine("Before Result");
var result = expr.Result;
Console.WriteLine(result);
public async Task<int> CreateTask1()
Console.WriteLine("CreateTask1");
return await Task.FromResult(4);
public async Task<int> CreateTask2()
Console.WriteLine("CreateTask2");
return await Task.FromResult(6);
public async Task<string> CreateTask3()
Console.WriteLine("CreateTask3");
return await Task.FromResult("The result is: ");
public static class TaskExtensions
public static async Task<B> Bind<A, B>(this Task<A> @this, Func<A, Task<B>> fn)
return await fn(await @this);
public static async Task<B> Map<A, B>(this Task<A> @this, Func<A, B> fn)
return await Task.FromResult(fn(await @this));
public static Task<C> SelectMany<A, B, C>(this Task<A> @this, Func<A, Task<B>> fn, Func<A, B, C> select)
Console.WriteLine("SelectMany");
return @this.Bind(a => fn(a).Map(b => select(a, b)));