Created
June 24, 2014 11:31
-
-
Save hodzanassredin/28c4208206d9d88908f5 to your computer and use it in GitHub Desktop.
tutorial2 finished monad transformer
This file contains hidden or 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.Threading.Tasks; | |
namespace GenericMonad | |
{ | |
public class Async | |
{ | |
Async () | |
{ | |
} | |
public class AsyncM<T>: Async, IMonad<T, Async> | |
{ | |
#region IMonad implementation | |
public IMonad<TB, Async> Return<TB> (TB val) | |
{ | |
return new AsyncM<TB> (Task<TB>.FromResult (val)); | |
} | |
//helper method two tasks composition | |
private static async Task<TB> BindTasks<TB> (Task<T> m, Func<T, Task<TB>> f) | |
{ | |
var r = await m; | |
return await f (r); | |
} | |
public IMonad<TB, Async> Bind<TB> (Func<T, IMonad<TB, Async>> f) | |
{ | |
return new AsyncM<TB> (BindTasks (this.Task, (t) => f (t).CastM<TB, AsyncM<TB>, Async> ().Task)); | |
} | |
#endregion | |
public AsyncM (Task<T> val) | |
{ | |
Task = val; | |
} | |
public Task<T> Task { | |
get; | |
set; | |
} | |
} | |
} | |
public static class AsyncMonad | |
{ | |
public static Func<Async.AsyncM<TB>> Lift<TB> (this Func<Task<TB>> f) | |
where TB : class | |
{ | |
return () => { | |
var res = f (); | |
return new Async.AsyncM<TB> (res); | |
}; | |
} | |
} | |
} |
This file contains hidden or 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; | |
namespace GenericMonad | |
{ | |
public class CheckedVal<T> | |
{ | |
CheckedVal (T val) | |
{ | |
Value = val; | |
} | |
public static CheckedVal<T> Success (T val) | |
{ | |
return new CheckedVal<T> (val){ IsFailed = false }; | |
} | |
public static CheckedVal<T> Fail () | |
{ | |
return new CheckedVal<T> (default(T)){ IsFailed = true }; | |
} | |
public static CheckedVal<T> ToCheck (T val) | |
{ | |
return val == null ? Fail () : Success (val); | |
} | |
public bool IsFailed { | |
get; | |
private set; | |
} | |
public T Value { | |
get; | |
private set; | |
} | |
public override string ToString () | |
{ | |
return string.Format ("[Check: IsFailed={0}, Value={1}]", IsFailed, Value); | |
} | |
} | |
} |
This file contains hidden or 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; | |
namespace GenericMonad | |
{ | |
public class Check | |
{ | |
Check () | |
{ | |
} | |
public class CheckM<T>: Check, IMonad<T, Check> | |
{ | |
#region IMonad implementation | |
public IMonad<TB, Check> Return<TB> (TB val) | |
{ | |
return CheckM<TB>.Success (val); | |
} | |
public IMonad<TB, Check> Bind<TB> (Func<T, IMonad<TB, Check>> f) | |
{ | |
return this.Value.IsFailed ? CheckM<TB>.Fail () : f (this.Value.Value); | |
} | |
#endregion | |
public CheckM (CheckedVal<T> val) | |
{ | |
Value = val; | |
} | |
public static CheckM<T> Success (T val) | |
{ | |
return new CheckM<T> (CheckedVal<T>.Success (val)); | |
} | |
public static CheckM<T> Fail () | |
{ | |
return new CheckM<T> (CheckedVal<T>.Fail ()); | |
} | |
public CheckedVal<T> Value { | |
get; | |
private set; | |
} | |
public override string ToString () | |
{ | |
return Value.ToString (); | |
} | |
} | |
} | |
} |
This file contains hidden or 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; | |
namespace GenericMonad | |
{ | |
public class CheckForT<TMI> | |
{ | |
CheckForT () | |
{ | |
} | |
public class CheckT<T>: CheckForT<TMI>, IMonad<T, CheckForT<TMI>> | |
{ | |
#region IMonad implementation | |
public IMonad<TB, CheckForT<TMI>> Return<TB> (TB val) | |
{ | |
return new CheckT<TB> (Value.Return<CheckedVal<TB>> (CheckedVal<TB>.Success (val))); | |
} | |
private IMonad<CheckedVal<TB>,TMI> BindInternal<TB> (CheckedVal<T> check, | |
Func<T, IMonad<TB, CheckForT<TMI>>> f) | |
{ | |
return check.IsFailed | |
? Value.Return<CheckedVal<TB>> (CheckedVal<TB>.Fail ()) | |
: f (check.Value).CastM<TB, CheckT<TB>,CheckForT<TMI>> ().Value; | |
} | |
public IMonad<TB, CheckForT<TMI>> Bind<TB> (Func<T, IMonad<TB, CheckForT<TMI>>> f) | |
{ | |
var tmp = Value.Bind<CheckedVal<TB>> (check => BindInternal (check, f)); | |
return new CheckT<TB> (tmp); | |
} | |
#endregion | |
public CheckT (IMonad<CheckedVal<T>,TMI> val) | |
{ | |
Value = val; | |
} | |
public IMonad<CheckedVal<T>,TMI> Value { | |
get; | |
private set; | |
} | |
} | |
} | |
public static class CheckMonad | |
{ | |
public static Func<Check.CheckM<TB>> Lift<TB> (this Func<TB> f) | |
where TB : class | |
{ | |
return () => { | |
var res = f (); | |
return new Check.CheckM<TB> (CheckedVal<TB>.ToCheck (res)); | |
}; | |
} | |
public static Func<Check.CheckM<TB>> Lift<TB> (this Func<CheckedVal<TB>> f) | |
where TB : class | |
{ | |
return () => { | |
var res = f (); | |
return new Check.CheckM<TB> (res); | |
}; | |
} | |
public static Func<CheckForT<TMI>.CheckT<TB>> LiftT<TB,TMI> (this Func<IMonad<TB,TMI>> f) | |
where TB : class | |
{ | |
Func<IMonad<CheckedVal<TB>,TMI>> checkF = () => { | |
var m = f (); | |
return m.Bind (val => m.Return (CheckedVal<TB>.ToCheck (val))); | |
}; | |
return () => { | |
var monad = checkF (); | |
return new CheckForT<TMI>.CheckT<TB> (monad); | |
}; | |
} | |
} | |
} |
This file contains hidden or 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; | |
namespace GenericMonad | |
{ | |
public interface IMonad<T, TMI> | |
{ | |
IMonad<TB,TMI> Return<TB> (TB val); | |
IMonad<TB,TMI> Bind<TB> (Func<T, IMonad<TB,TMI>> f); | |
} | |
public static class MonadSyntax | |
{ | |
public static TM CastM<T, TM, TMB> (this IMonad<T, TMB> m) | |
where TM : IMonad<T, TMB> | |
{ | |
return (TM)m;//safe for single inheritance | |
} | |
public static IMonad<V, TMI> SelectMany<T, TMI, U, V> | |
( | |
this IMonad<T, TMI> id, | |
Func<T, IMonad<U, TMI>> k, | |
Func<T, U, V> s) | |
{ | |
return id.Bind (x => k (x).Bind (y => id.Return (s (x, y)))); | |
} | |
public static IMonad<B, TMI> Select<A, B, TMI> (this IMonad<A, TMI> a, Func<A, IMonad<B, TMI>> select) | |
{ | |
return a.Bind (aval => select (aval)); | |
} | |
} | |
} |
This file contains hidden or 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.Net; | |
using System.Threading.Tasks; | |
namespace GenericMonad | |
{ | |
class MainClass | |
{ | |
public static Task<String> GetData () | |
{ | |
//return Task<String>.FromResult ((string)null); | |
return new WebClient ().DownloadStringTaskAsync (new Uri ("http://google.com")); | |
} | |
static void Main (string[] args) | |
{ | |
//expected Check<Test> but Check<Check<Test>> | |
var getData = CheckMonad.LiftT (AsyncMonad.Lift (GetData)); | |
var res = | |
from a in getData () | |
from b in getData () | |
select a.Substring (0, 10) + b.Substring (10, 20); | |
var checkT = res.CastM<string, CheckForT<Async>.CheckT<string>, CheckForT<Async> > (); | |
var task = checkT.Value.CastM<CheckedVal<string>, Async.AsyncM<CheckedVal<string>>, Async> ().Task; | |
Console.WriteLine (task.Result); | |
Console.WriteLine ("finished!"); | |
Console.ReadLine (); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment