Last active
August 29, 2015 14:07
-
-
Save matarillo/1497940cb6576675002c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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