Created
March 6, 2013 07:32
-
-
Save j0057/5097428 to your computer and use it in GitHub Desktop.
Working through the code from http://ericlippert.com/2013/03/04/monads-part-four/
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; | |
using System.Threading.Tasks; | |
namespace FunWithMonads | |
{ | |
static class Program | |
{ | |
/* | |
* Nullable<T> | |
*/ | |
static Nullable<T> SimpleNullable<T>(T item) | |
where T : struct | |
{ | |
return new Nullable<T>(item); | |
} | |
static Nullable<int> AddOne_1(Nullable<int> nullable) | |
{ | |
if (nullable.HasValue) | |
{ | |
return SimpleNullable(nullable.Value + 1); | |
} | |
else | |
{ | |
return new Nullable<int>(); | |
} | |
} | |
static Nullable<R> ApplyFunction<A, R>(Nullable<A> nullable, Func<A, R> function) | |
where A : struct | |
where R : struct | |
{ | |
if (nullable.HasValue) | |
{ | |
return SimpleNullable(function(nullable.Value)); | |
} | |
else | |
{ | |
return new Nullable<R>(); | |
} | |
} | |
public static Nullable<R> Bind<A, R>(this Nullable<A> nullable, Func<A, Nullable<R>> function) | |
where A : struct | |
where R : struct | |
{ | |
return nullable.HasValue | |
? function(nullable.Value) | |
: null; | |
} | |
static Nullable<int> AddOne_2(Nullable<int> nullable) | |
{ | |
return ApplyFunction(nullable, (int value) => value + 1); | |
} | |
static Nullable<double> DivideByTwo(Nullable<int> nullable) | |
{ | |
return ApplyFunction(nullable, (int value) => value / 2.0); | |
} | |
static Nullable<double> DivideByTwo_2(Nullable<int> nullable) | |
{ | |
return nullable.Bind<int, double>((int value) => value / 2.0); | |
} | |
/* | |
* OnDemand<T> == Func<T> | |
*/ | |
delegate T OnDemand<T>(); | |
static OnDemand<T> SimpleOnDemand<T>(T item) | |
{ | |
return () => item; | |
} | |
static OnDemand<int> AddOne_1(OnDemand<int> onDemand) | |
{ | |
return () => onDemand() + 1; | |
} | |
static OnDemand<R> ApplyFunction<A, R>(OnDemand<A> onDemand, Func<A, R> function) | |
{ | |
return () => function(onDemand()); | |
} | |
static OnDemand<int> AddOne_2(OnDemand<int> onDemand) | |
{ | |
return ApplyFunction(onDemand, (int unwrapped) => unwrapped + 1); | |
} | |
/* | |
* Lazy<T> | |
*/ | |
static Lazy<T> SimpleLazy<T>(T item) | |
{ | |
return new Lazy<T>(() => item); | |
} | |
static Lazy<int> AddOne_1(Lazy<int> lazy) | |
{ | |
return new Lazy<int>(() => lazy.Value + 1); | |
} | |
static Lazy<R> ApplyFunction<A, R>(Lazy<A> lazy, Func<A, R> function) | |
{ | |
return new Lazy<R>(() => function(lazy.Value)); | |
} | |
static Lazy<int> AddOne_2(Lazy<int> lazy) | |
{ | |
return ApplyFunction(lazy, (int unwrapped) => unwrapped + 1); | |
} | |
/* | |
* Task<T> | |
*/ | |
static Task<T> SimpleTask<T>(T item) | |
{ | |
return new Task<T>(() => item); | |
} | |
static Task<int> AddOne_1(Task<int> task) | |
{ | |
return task.ContinueWith<int>(t => t.Result + 1); | |
} | |
static Task<R> ApplyFunction<A, R>(Task<A> task, Func<A, R> function) | |
{ | |
return task.ContinueWith(t => function(t.Result)); | |
} | |
static Task<int> AddOne_2(Task<int> task) | |
{ | |
return ApplyFunction(task, (int unwrapped) => unwrapped + 1); | |
} | |
/* | |
* IEnumerable<T> | |
*/ | |
static IEnumerable<T> SimpleEnumerable<T>(T item) | |
{ | |
yield return item; | |
} | |
static IEnumerable<int> AddOne_1(IEnumerable<int> items) | |
{ | |
foreach (int unwrapped in items) | |
{ | |
yield return unwrapped + 1; | |
} | |
} | |
static IEnumerable<R> ApplyFunction<A, R>(IEnumerable<A> items, Func<A, R> function) | |
{ | |
foreach (A unwrapped in items) | |
{ | |
yield return function(unwrapped); | |
} | |
} | |
static IEnumerable<int> AddOne_2(IEnumerable<int> items) | |
{ | |
return ApplyFunction(items, (int unwrapped) => unwrapped + 1); | |
} | |
/* | |
* Prove it | |
*/ | |
static void Main(string[] args) | |
{ | |
Nullable<int> nullable = 41; | |
OnDemand<int> onDemand = () => 2; | |
Lazy<int> lazy = new Lazy<int>(() => 3); | |
Task<int> task = new Task<int>(() => 4); | |
IEnumerable<int> sequence = new int[] { 5 }; | |
var aa_1 = AddOne_1(nullable); | |
var aa_1_ = aa_1.Value; | |
var aa_2 = AddOne_2(nullable); | |
var aa_2_ = aa_2.Value; | |
var aa_3 = DivideByTwo(nullable); | |
var aa_3_ = aa_3.Value; | |
var bb_1 = AddOne_1(onDemand); | |
var bb_1_ = bb_1(); | |
var bb_2 = AddOne_2(onDemand); | |
var bb_2_ = bb_2(); | |
var cc_1 = AddOne_1(lazy); | |
var cc_1_ = cc_1.Value; | |
var cc_2 = AddOne_2(lazy); | |
var cc_2_ = cc_2.Value; | |
//task.Start(); | |
var dd_1 = AddOne_1(task); | |
var dd_1_ = dd_1.Result; | |
var dd_2 = AddOne_2(task); | |
var dd_2_ = dd_2.Result; | |
var ee_1 = AddOne_1(sequence); | |
var ee_1_ = ee_1.ToArray(); | |
var ee_2 = AddOne_2(sequence); | |
var ee_2_ = ee_2.ToArray(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment