does x support y, pt. i
Joshua HawxwellPossibly, …
using System;
public interface IMonad<T>
{
IMonad<U> Bind<U>(Func<T, IMonad<U>> f);
IMonad<T> Unit(T value);
}
public static class Monad
{
public static IMonad<U> Lift<T, U>(Func<T, U> f, IMonad<T> mx, IMonad<U> my)
{
return mx.Bind(x => my.Unit(f(x)));
}
public static IMonad<V> Lift2<T, U, V>(Func<T, U, V> op, IMonad<T> mx, IMonad<U> my, IMonad<V> mz) {
return mx.Bind(x => my.Bind(y => mz.Unit(op(x, y))));
}
}
public class Maybe<T> : IMonad<T>
{
private bool _nothing;
private T _value;
private Maybe() { _nothing = true; }
private Maybe(T value) { _value = value; }
public static Maybe<T> Nothing()
{
return new Maybe<T>();
}
public static Maybe<T> Just(T value)
{
return new Maybe<T>(value);
}
public IMonad<U> Bind<U>(Func<T, IMonad<U>> f)
{
return _nothing
? Maybe<U>.Nothing()
: f(_value);
}
public IMonad<T> Unit(T value)
{
return Just(value);
}
public override string ToString()
{
return _nothing
? "Nothing"
: string.Format("Just({0})", _value);
}
}
public class PossibleCalculator
{
public IMonad<int> Add(Maybe<int> mx, Maybe<int> my)
{
return Monad.Lift2<int, int, int>((x, y) => x + y, mx, my, Maybe<int>.Nothing());
}
public IMonad<int> Neg(Maybe<int> mx)
{
return Monad.Lift<int, int>(x => -x, mx, Maybe<int>.Nothing());
}
}
public class Program
{
private static Maybe<int> GetLine(string pre)
{
Console.Write(pre);
var line = Console.ReadLine();
int a;
if (!int.TryParse(line, out a))
return Maybe<int>.Nothing();
return Maybe<int>.Just(a);
}
public static void Main()
{
Console.WriteLine("Enter two numbers:");
var a = GetLine(" a) ");
var b = GetLine(" b) ");
Console.WriteLine("\nThen:");
var calc = new PossibleCalculator();
Console.WriteLine(" a + b = {0}", calc.Add(a, b));
Console.WriteLine(" -a = {0}", calc.Neg(a));
Console.WriteLine(" -b = {0}", calc.Neg(b));
}
}
I’ll leave implementing ListM<T> : IMonad<T>
as an exercise for the reader.