Skip to content

Instantly share code, notes, and snippets.

@matarillo
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matarillo/11393891 to your computer and use it in GitHub Desktop.
Save matarillo/11393891 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main(string[] args)
{
var m =
from x in Maybe.Instance.Unit(12)
from y in Maybe.Instance.Unit(34)
select x + y;
var message =
m.HasValue()
? m.Value().ToString()
: "Nothing";
Console.WriteLine(message);
}
}
public abstract class TypeClass<TImpl>
{
}
public abstract class Functor<TImpl> : TypeClass<TImpl>
{
public abstract Value<TImpl, TResult> Map<T, TResult>(
Value<TImpl, T> m,
Func<T, TResult> f);
}
public abstract class Applicative<TImpl> : Functor<TImpl>
{
public abstract Value<TImpl, T> Pure<T>(T value);
public abstract Value<TImpl, TResult> Ap<T, TResult>(
Value<TImpl, T> m,
Value<TImpl, Func<T, TResult>> mf);
public override Value<TImpl, TResult> Map<T, TResult>(
Value<TImpl, T> m,
Func<T, TResult> f)
{
return Ap(m, Pure(f));
}
}
public abstract class Monad<TImpl> : Applicative<TImpl>
{
public abstract Value<TImpl, T> Unit<T>(T value);
public abstract Value<TImpl, TResult> Bind<T, TResult>(
Value<TImpl, T> m,
Func<T, Value<TImpl, TResult>> f);
public override Value<TImpl, T> Pure<T>(T value)
{
return Unit(value);
}
public override Value<TImpl, TResult> Ap<T, TResult>(
Value<TImpl, T> m,
Value<TImpl, Func<T, TResult>> mf)
{
return Bind(m, x => Bind(mf, f => Unit(f(x))));
}
}
public class Maybe : Monad<Maybe>
{
public static readonly Maybe Instance = new Maybe();
public static Value<Maybe, T> Nothing<T>()
{
return new Value<Maybe, T>();
}
public override Value<Maybe, T> Unit<T>(T value)
{
return new Value<Maybe, T>().SetValue(value);
}
public override Value<Maybe, TResult> Bind<T, TResult>(
Value<Maybe, T> m,
Func<T, Value<Maybe, TResult>> f)
{
return (m.HasValue()) ? f(m.Value()) : Nothing<TResult>();
}
}
public class Value<TImpl, T>
{
private readonly Dictionary<string, object> _fields
= new Dictionary<string, object>();
public void Set(string name, object value)
{
_fields[name] = value;
}
public TField Get<TField>(string name)
{
object o;
if (_fields.TryGetValue(name, out o))
{
return (TField)o;
}
return default(TField);
}
}
public static class MonadEx
{
public static Value<TMonad, TResult> SelectMany<TMonad, TSource, TCollection, TResult>(
this Value<TMonad, TSource> source,
Func<TSource, Value<TMonad, TCollection>> collectionSelector,
Func<TSource, TCollection, TResult> resultSelector)
where TMonad : Monad<TMonad>, new()
{
var monad = new TMonad();
return
monad.Bind(source, x=>
monad.Bind(collectionSelector(x), y=>
monad.Unit(resultSelector(x,y))));
}
}
public static class MaybeEx
{
public static Value<Maybe, T> SetValue<T>(this Value<Maybe, T> m, T value)
{
m.Set("HasValue", true);
m.Set("Value", value);
return m;
}
public static bool HasValue<T>(this Value<Maybe, T> m)
{
return m.Get<bool>("HasValue");
}
public static T Value<T>(this Value<Maybe, T> m)
{
if (m.HasValue())
{
return m.Get<T>("Value");
}
throw new InvalidOperationException();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment