Skip to content

Instantly share code, notes, and snippets.

@matarillo
Last active August 29, 2015 14:07
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/1497940cb6576675002c to your computer and use it in GitHub Desktop.
Save matarillo/1497940cb6576675002c to your computer and use it in GitHub Desktop.
using System;
class Program
{
static void Main(string[] args)
{
var monad = Maybe.Monad;
var m1 = monad.Unit(12);
var m2 = monad.Unit(34);
var m =
monad.Bind(m1, x1 =>
monad.Bind(m2, x2 =>
monad.Unit(x1 + x2)))
as Maybe<int>;
var message =
m.HasValue
? m.Value.ToString()
: "Nothing";
Console.WriteLine(message);
}
}
public interface _<T, TValue>
{
}
#region functor
public abstract class Functor<T>
{
public abstract _<T, TOut> Map<TIn, TOut>(_<T, TIn> f, Func<TIn, TOut> func);
}
public static class Functor
{
public static _<T, TOut> Map<T, TIn, TOut>(Functor<T> instance, _<T, TIn> f, Func<TIn, TOut> func)
{
return instance.Map(f, func);
}
}
#endregion
#region applicative
public abstract class Applicative<T> : Functor<T>
{
public abstract _<T, TValue> Pure<TValue>(TValue value);
public abstract _<T, TOut> Ap<TIn, TOut>(_<T, TIn> a, _<T, Func<TIn, TOut>> func);
public override _<T, TOut> Map<TIn, TOut>(_<T, TIn> f, Func<TIn, TOut> func)
{
return Ap(f, Pure(func));
}
}
public static class Applicative
{
public static _<T, TValue> Pure<T, TValue>(Applicative<T> instance, TValue value)
{
return instance.Pure(value);
}
public static _<T, TOut> Ap<T, TIn, TOut>(Applicative<T> instance, _<T, TIn> a, _<T, Func<TIn, TOut>> func)
{
return instance.Ap(a, func);
}
// 必要ないかも?
public static _<T, TOut> Map<T, TIn, TOut>(Applicative<T> instance, Func<TIn, TOut> func, _<T, TIn> f)
{
return instance.Map(f, func);
}
}
#endregion
#region monad
public abstract class Monad<T> : Applicative<T>
{
public abstract _<T, TValue> Unit<TValue>(TValue value);
public abstract _<T, TOut> Bind<TIn, TOut>(_<T, TIn> m, Func<TIn, _<T, TOut>> mf);
public override _<T, TValue> Pure<TValue>(TValue value)
{
return Unit(value);
}
public override _<T, TOut> Ap<TIn, TOut>(_<T, TIn> a, _<T, Func<TIn, TOut>> af)
{
return Bind(a, x => Bind(af, f => Unit(f(x))));
}
}
public static class Monad
{
public static _<T, TValue> Unit<T, TValue>(Monad<T> instance, TValue value)
{
return instance.Unit(value);
}
public static _<T, TOut> Bind<T, TIn, TOut>(Monad<T> instance, _<T, TIn> m, Func<TIn, _<T, TOut>> mf)
{
return instance.Bind(m, mf);
}
// 必要ないかも?
public static _<T, TValue> Pure<T, TValue>(Monad<T> instance, TValue value)
{
return instance.Pure(value);
}
// 必要ないかも?
public static _<T, TOut> Ap<T, TIn, TOut>(Monad<T> instance, _<T, TIn> m, _<T, Func<TIn, TOut>> mf)
{
return instance.Ap(m, mf);
}
// 必要ないかも?
public static _<T, TOut> Map<T, TIn, TOut>(Monad<T> instance, _<T, TIn> m, Func<TIn, TOut> func)
{
return instance.Map(m, func);
}
}
#endregion
#region Maybe
public class Maybe<T> : _<Maybe.µ, T>
{
private readonly bool hasValue;
private readonly T value;
public static readonly Maybe<T> Nothing = new Maybe<T>();
// ほんとうはMaybe.µからしか呼ばせたくないのだが……
internal Maybe()
{
}
// ほんとうはMaybe.µからしか呼ばせたくないのだが……
internal Maybe(T value)
{
this.hasValue = true;
this.value = value;
}
public bool HasValue
{
get { return hasValue; }
}
public T Value
{
get
{
if (!hasValue) throw new InvalidOperationException();
return value;
}
}
}
public static class Maybe
{
public static readonly Monad<Maybe.µ> Monad = new µ();
public sealed class µ : Monad<Maybe.µ>
{
internal µ() { }
public override _<µ, TValue> Unit<TValue>(TValue value)
{
return new Maybe<TValue>(value);
}
public override _<µ, TOut> Bind<TIn, TOut>(_<µ, TIn> m, Func<TIn, _<µ, TOut>> mf)
{
var maybe = (Maybe<TIn>)m; // キャストに失敗しないはずという前提
return (maybe.HasValue)
? mf(maybe.Value)
: Maybe<TOut>.Nothing;
}
}
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment