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/11392331 to your computer and use it in GitHub Desktop.
Save matarillo/11392331 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main(string[] args)
{
Value<Maybe, int> m1 = Maybe.Instance.Unit(12);
Value<Maybe, int> m2 = Maybe.Instance.Unit(34);
Value<Maybe, int> m3 =
Maybe.Instance.Bind(m1, x =>
Maybe.Instance.Bind(m2, y =>
Maybe.Instance.Unit(x + y)));
string message =
m3.HasValue()
? m3.Value().ToString()
: "Nothing";
Console.WriteLine(message);
}
}
public abstract class Functor<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 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