Skip to content

Instantly share code, notes, and snippets.

@hodzanassredin
Last active September 19, 2017 17:27
Show Gist options
  • Save hodzanassredin/662b06daabb4f241d2f3 to your computer and use it in GitHub Desktop.
Save hodzanassredin/662b06daabb4f241d2f3 to your computer and use it in GitHub Desktop.
monad tutorial
using System;
using System.Threading.Tasks;
using System.Net;
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 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);
};
}
}
class MainClass
{
public static Task<String> GetData ()
{
return new WebClient().DownloadStringTaskAsync(new Uri("http://google.com"));
}
static void Main (string[] args)
{
//expected Check<Test> but Check<Check<Test>>
var getData = AsyncMonad.Lift (GetData);
var res =
from a in getData ()
from b in getData ()
select a.Substring(0,10) + b.Substring(10,20);
var task = res.CastM<string, Async.AsyncM<string>, Async> ().Task;
Console.WriteLine (task.Result);
Console.WriteLine ("finished!");
Console.ReadLine ();
}
}
}
using System;
namespace HigherKind
{
// interface IFunctor<T<_>> {
// T<B> FMap<A, B>(Func<A, B> f, T<A> a);
// }
public interface IGeneric<T, TCONTAINER>
{
}
public static class GenericExts
{
public static TM UpCast<T, TM, TMB> (this IGeneric<T, TMB> m)
where TM : IGeneric<T, TMB>
{
return (TM)m;//safe for single inheritance
}
public static IGeneric<T, TMB> DownCast<T, TM, TMB> (this TM m)
where TM : IGeneric<T, TMB>
{
return (TM)m;//safe for single inheritance
}
}
public interface IFunctor<T>
{
CB FMap<A, B, CA, CB> (Func<A, B> f, CA a)
where CA : IGeneric<A, T>
where CB : IGeneric<B, T>;
}
public interface IFunctorSelf<TGENERIC, TSELF, TVALUE>
where TSELF : IGeneric<TVALUE, TGENERIC>
{
CB FMap<B, CB> (Func<TVALUE, B> f)
where CB : IGeneric<B, TGENERIC>;
}
public abstract class Wrapper
{
private Wrapper ()
{
}
public class WrapperImpl<T> : Wrapper, IGeneric<T, Wrapper>, IFunctorSelf<Wrapper, WrapperImpl<T> , T>
{
#region IFunctorSelf implementation
public CB FMap<B, CB> (Func<T, B> f) where CB : IGeneric<B, Wrapper>
{
var res = new WrapperImpl<B> (f (Value));
return res.Cast<B, CB,Wrapper> ();
}
#endregion
public WrapperImpl (T val)
{
Value = val;
}
public T Value {
get;
set;
}
}
}
class MainClass
{
public static void Main (string[] args)
{
var a = new Wrapper.WrapperImpl<int> (1);
var b = a.FMap<int, Wrapper.WrapperImpl<int>> (x => -x);
Console.WriteLine ("Value is: " + b.Value);
Console.ReadLine ();
}
}
}
using System;
namespace MonadTutorial
{
public class Check<T>
{
private Check (T val)
{
Value = val;
}
public static Check<T> Success (T val)
{
return new Check<T> (val){ IsFailed = false };
}
public static Check<T> Fail ()
{
return new Check<T> (default(T)){ IsFailed = true };
}
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);
}
}
public static class CheckMonad
{
public static Check<T> Return<T> (this T value)
{
return Check<T>.Success (value);
}
public static Check<U> Bind<T, U> (this Check<T> m, Func<T, Check<U>> k) //bind
{
return m.IsFailed ? Check<U>.Fail () : k (m.Value);
}
public static Func<Check<T>> Lift<T> (Func<T> f)
where T : class
{
return () => {
var res = f ();
return res == null ? Check<T>.Fail () : Check<T>.Success (res);
};
}
public static Check<V> SelectMany<T, U, V> (
this Check<T> id,
Func<T, Check<U>> k,
Func<T, U, V> s)
{
return id.Bind (x => k (x).Bind (y => s (x, y).Return ()));
}
}
class Test
{
public Test ()
{
}
}
class MainClass
{
public static bool Bool ()
{
return new Random ().Next () % 2 == 0 ? true : false;
}
public static T GetData<T> ()
where T : class, new()
{
return Bool () ? null : new T ();
}
static void Main (string[] args)
{
//expected Check<Test> but Check<Check<Test>>
var getData = CheckMonad.Lift<Test> (GetData<Test>);
var res =
from a in getData ()
from b in getData ()
select a == b ? a : b;
Console.WriteLine (res);
Console.WriteLine ("finished!");
}
}
}
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 Cast<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 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.IsFailed ? CheckM<TB>.Fail () : f (this.Value);
}
#endregion
CheckM (T val)
{
Value = val;
}
public static CheckM<T> Success (T val)
{
return new CheckM<T> (val){ IsFailed = false };
}
public static CheckM<T> Fail ()
{
return new CheckM<T> (default(T)){ IsFailed = true };
}
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);
}
}
}
public static class CheckMonad
{
public static Func<Check.CheckM<TB>> Lift<TB> (this Func<TB> f)
where TB : class
{
return () => {
var res = f ();
return res == null ? Check.CheckM<TB>.Fail () : Check.CheckM<TB>.Success (res);
};
}
}
class MainClass
{
public static bool Bool ()
{
return new Random ().Next () % 2 == 0;
}
public static T GetData<T> ()
where T : class, new()
{
return Bool () ? null : new T ();
}
static void Main (string[] args)
{
//expected Check<Test> but Check<Check<Test>>
var getData = CheckMonad.Lift<Object> (GetData<Object>);
var res =
from a in getData ()
from b in getData ()
select a == b ? a : b;
Check.CheckM<Object> m = res.Cast<Object, Check.CheckM<Object>, Check> ();
Console.WriteLine (m);
Console.WriteLine ("finished!");
}
}
}
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 Cast<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 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.IsFailed ? CheckM<TB>.Fail () : f (this.Value);
}
#endregion
CheckM (T val)
{
Value = val;
}
public static CheckM<T> Success (T val)
{
return new CheckM<T> (val){ IsFailed = false };
}
public static CheckM<T> Fail ()
{
return new CheckM<T> (default(T)){ IsFailed = true };
}
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);
}
}
}
public class CheckForT
{
CheckForT ()
{
}
public class CheckT<T,TMM>: CheckForT, IMonad<IMonad<T, TMM>, CheckForT>
{
#region IMonad implementation
public IMonad<TB, CheckForT> Return<TB> (TB val)
{
return C
}
public IMonad<TB, CheckForT> Bind<TB> (Func<IMonad<T, TMM>, IMonad<TB, CheckForT>> f)
{
throw new NotImplementedException ();
}
#endregion
CheckT (IMonad<T, TMM> val)
{
Value = val;
}
public static CheckT<T,TMM> Success (IMonad<T, TMM> val)
{
return new CheckT<T,TMM> (val){ IsFailed = false };
}
public static CheckT<T,TMM> Fail ()
{
return new CheckT<T,TMM> (default(IMonad<T, TMM>)){ IsFailed = true };
}
public bool IsFailed {
get;
private set;
}
public IMonad<T, TMM> Value {
get;
private set;
}
public override string ToString ()
{
return string.Format ("[Check: IsFailed={0}, Value={1}]", IsFailed, Value);
}
}
}
public static class CheckMonad
{
public static Func<Check.CheckM<TB>> Lift<TB> (this Func<TB> f)
where TB : class
{
return () => {
var res = f ();
return res == null ? Check.CheckM<TB>.Fail () : Check.CheckM<TB>.Success (res);
};
}
}
class MainClass
{
public static bool Bool ()
{
return new Random ().Next () % 2 == 0;
}
public static T GetData<T> ()
where T : class, new()
{
return Bool () ? null : new T ();
}
static void Main (string[] args)
{
//expected Check<Test> but Check<Check<Test>>
var getData = CheckMonad.Lift<Object> (GetData<Object>);
var res =
from a in getData ()
from b in getData ()
select a == b ? a : b;
Check.CheckM<Object> m = res.Cast<Object, Check.CheckM<Object>, Check> ();
Console.WriteLine (m);
Console.WriteLine ("finished!");
}
}
}
using System;
namespace MonadTutorial
{
class Tut
{
public static bool Bool ()
{
return new Random ().Next () % 2 == 0 ? true : false;
}
public static T GetData<T> ()
where T : class, new()
{
return Bool () ? null : new T ();
}
public static void Compare (string[] args)
{
var a = GetData<Object> ();
var b = GetData<Object> ();
if (a == b)
Console.WriteLine ("a == b");
else
Console.WriteLine ("a != b");
Console.WriteLine ("finished!");
}
public static void DefesiveCompare (string[] args)
{
var a = GetData<Object> ();
if (a == null) {
Console.WriteLine ("Can't compare");
return;
}
var b = GetData<Object> ();
if (b == null) {
Console.WriteLine ("Can't compare");
return;
}
if (a == b)
Console.WriteLine ("a == b");
else
Console.WriteLine ("a != b");
Console.WriteLine ("finished!");
}
public static bool Defend (object o)
{
if (o == null) {
Console.WriteLine ("Can't compare");
return false;
}
return true;
}
public static void DefesiveCompareDry (string[] args)
{
var a = GetData<Object> ();
if (Defend (a))
return;
var b = GetData<Object> ();
if (Defend (b))
return;
if (a == b)
Console.WriteLine ("a == b");
else
Console.WriteLine ("a != b");
Console.WriteLine ("finished!");
}
public static string Defend2 (object a, Func<object, string> f)
{
return a == null ? "Can't compare" : f (a);
}
public static void DefesiveCompareDry2 (string[] args)
{
var res = Defend2 (GetData<Object> (),
(a) => Defend2 (GetData<Object> (),
(b) => a == b ? "a == b" : "a != b"));
Console.WriteLine (res);
Console.WriteLine ("finished!");
}
class Test
{
public Test ()
{
}
}
// public static TB Defend2Generic<TA,TB> (TA a, Func<TA, TB> f)
// where TA : class//applied only for TA which can be null
// {
// return a == null ? "Can't compare" : f (a);
// }
public class Check<T> where T : class
{
public Check (String errorMessage)
{
IsFailed = true;
FailMesssage = errorMessage;
}
public Check (T val)
{
Value = val;
}
public bool IsFailed {
get;
private set;
}
public string FailMesssage {
get;
private set;
}
public T Value {
get;
private set;
}
public override string ToString ()
{
return string.Format ("[Check: IsFailed={0}, FailMesssage={1}, Value={2}]", IsFailed, FailMesssage, Value);
}
}
public static Check<TB> Defend2Generic2<TA,TB> (TA a, Func<TA, TB> f)
where TA : class
where TB : class//applied only for TB and TA which can be null
{
return a == null ? new Check<TB> ("Can't compare") : new Check<TB> (f (a));
}
// public static void DefesiveCompareGeneric2 (string[] args)
// {
// //expected Check<Test> but Check<Check<Test>>
// Check<Test> res = Defend2Generic2 (GetData<Test> (),
// a => Defend2Generic2 (GetData<Test> (),
// b => a == b ? a : b));
//
// Console.WriteLine (res);
// Console.WriteLine ("finished!\n");
// }
public class Check2<T>
where T : class
{
private Check2 (T val)
{
Value = val;
}
public static Check2<T> Success (T val)
{
return new Check2<T> (val){ IsFailed = false };
}
public static Check2<T> Fail ()
{
return new Check2<T> (null){ IsFailed = true };
}
public bool IsFailed {
get;
private set;
}
public T Value {
get;
private set;
}
public override string ToString ()
{
return string.Format ("[Check: IsFailed={0}, Value={2}]", IsFailed, Value);
}
}
public static Check2<TB> Defend2Generic3<TA,TB> (Check2<TA> a, Func<TA, Check2<TB>> f)
where TA : class//applied only for TA which can be null
where TB : class//applied only for TB which can be null
{
return a.IsFailed ? Check2<TB>.Fail () : f (a.Value);
}
public static Func<Check2<T>> Lift<T> (Func<T> f)
where T : class
{
return () => {
var res = f ();
return res == null ? Check2<T>.Fail () : Check2<T>.Success (res);
};
}
// public static void DefesiveCompareGeneric3 (string[] args)
// {
//
// var getData = Lift<Test> (GetData<Test>);
// Check2<Test> res = Defend2Generic3<Test,Test> (getData (),
// a => Defend2Generic3<Test,Test> (getData (),
// b => a == b ? a : b));
// //unable to cast test to Check<Test>
// Console.WriteLine (res);
// Console.WriteLine ("finished!\n");
// }
public class Check3<T>
{
private Check3 (T val)
{
Value = val;
}
public static Check3<T> Success (T val)
{
return new Check3<T> (val){ IsFailed = false };
}
public static Check3<T> Fail ()
{
return new Check3<T> (default(T)){ IsFailed = true };
}
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);
}
}
public static Check3<TB> Defend2Generic4<TA,TB> (Check3<TA> a, Func<TA, Check3<TB>> f)
{
return a.IsFailed ? Check3<TB>.Fail () : f (a.Value);
}
public static Func<Check3<T>> Lift2<T> (Func<T> f)
where T : class
{
return () => {
var res = f ();
return res == null ? Check3<T>.Fail () : Check3<T>.Success (res);
};
}
public static Check3<T> Return <T> (T val)
{
return Check3<T>.Success (val);
}
public static void DefesiveCompareGeneric4 (string[] args)
{
//expected Check<Test> but Check<Check<Test>>
var getData = Lift2<Test> (GetData<Test>);
Check3<Test> res = Defend2Generic4<Test,Test> (getData (),
a => Defend2Generic4<Test,Test> (getData (),
b => Return (a == b ? a : b)));
Console.WriteLine (res);
Console.WriteLine ("finished!");
}
//generalization
// interface IMonad<T>
// {
// TB Bind<TMA,TMB,TA,TB> (TMA a, Func<TA, TMB> f)
// where TMA : IMonad<TA>
// where TMB : IMonad<TB>;
// }
//
// class CheckM<T> : IMonad<T>
// {
// T _obj;
//
// private CheckM (T obj)
// {
// _obj = obj;
// }
//
// public TB Bind<TA, TB> (Check<TA> a, Func<TA, TB> f)
// {
// throw new NotImplementedException ();
// }
// }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment