does x support y, pt. i

Possibly, …

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.