Skip to content

Instantly share code, notes, and snippets.

@kana
Created June 22, 2011 10:07
Show Gist options
  • Save kana/1039805 to your computer and use it in GitHub Desktop.
Save kana/1039805 to your computer and use it in GitHub Desktop.
Monad in C# (work in progress)
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using MonadSharp;
namespace Test
{
[TestClass()]
public class Test
{
[TestMethod()]
public void MaybeTest()
{
AreEqual(Just(10), Just(10));
AreEqual(Just(5), Just(10).Bind(a => Divide(a, 2)));
AreEqual(Nothing(), Just(10).Bind(a => Divide(a, 0)));
AreEqual(Nothing(), Just(10).Bind(a => Divide(a, 0)).Bind(a => Divide(a, 2)));
AreEqual(Nothing(), Just(10) | (a => Divide(a, 0)) | (a => Divide(a, 2)));
}
private void AreEqual(Maybe<int> expected, Maybe<int> actual)
{
Assert.AreEqual(expected.Look(null, x => (object)x), actual.Look(null, x => (object)x));
}
private Maybe<int> Divide(int dividend, int divisor)
{
if (divisor == 0)
return Nothing();
else
return Just(dividend / divisor);
}
private Just<int> Just(int plainValue)
{
return new Just<int>(plainValue);
}
private Nothing<int> Nothing()
{
return Nothing<int>.Value;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MonadSharp
{
class Program
{
static void Main(string[] args)
{
}
}
public abstract class Monad<TValue, TMonad> where TMonad : Monad<TValue, TMonad>
{
public abstract TMonad Bind(Func<TValue, TMonad> other);
public static TMonad operator |(Monad<TValue, TMonad> a, Func<TValue, TMonad> b)
{
return a.Bind(b);
}
}
public class Maybe<T> : Monad<T, Maybe<T>>
{
protected T Value {get; set;}
public override Maybe<T> Bind(Func<T, Maybe<T>> other)
{
if (this == Nothing<T>.Value)
return this;
else
return other(this.Value);
}
public TResult Look<TResult>(TResult fallbackValue, Func<T, TResult> f)
{
if (this == Nothing<T>.Value)
return fallbackValue;
else
return f(this.Value);
}
public T Look(T fallbackValue)
{
return Look(fallbackValue, x => x);
}
}
public class Nothing<T> : Maybe<T>
{
private static Nothing<T> theNothing = new Nothing<T>();
public static new Nothing<T> Value {get {return theNothing;}}
private Nothing()
{
}
}
public class Just<T> : Maybe<T>
{
public Just(T plainValue)
{
Value = plainValue;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment