Created
November 13, 2012 06:01
-
-
Save masaru-b-cl/4064229 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
// Refer to | |
// matarillo.com: モナドの驚異 | |
// http://matarillo.com/general/monads.php | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Monads | |
{ | |
class Identity<T> | |
{ | |
public T Value { get; private set; } | |
public Identity(T value) { this.Value = value; } | |
} | |
class Maybe<T> | |
{ | |
public readonly static Maybe<T> Nothing = new Maybe<T>(); | |
public T Value { get; private set; } | |
public bool HasValue { get; private set; } | |
public Maybe() | |
{ | |
HasValue = false; | |
} | |
public Maybe(T value) | |
{ | |
Value = value; | |
HasValue = true; | |
} | |
} | |
delegate Answer K<T, Answer>(Func<T, Answer> k); | |
static class MonadsExtensions | |
{ | |
public static Identity<T> ToIdentity<T>(this T value) | |
{ | |
return new Identity<T>(value); | |
} | |
public static Identity<U> SelectMany<T, U>(this Identity<T> id, Func<T, Identity<U>> k) | |
{ | |
return k(id.Value); | |
} | |
public static Identity<V> SelectMany<T, U, V> | |
(this Identity<T> id, Func<T, Identity<U>> k, Func<T, U, V> s) | |
{ | |
return id.SelectMany( | |
x => k(x).SelectMany( | |
y => s(x, y).ToIdentity())); | |
} | |
public static Maybe<T> ToMaybe<T>(this T value) | |
{ | |
return new Maybe<T>(value); | |
} | |
public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k) | |
{ | |
if (!m.HasValue) | |
return Maybe<U>.Nothing; | |
return k(m.Value); | |
} | |
public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> m, Func<T, Maybe<U>> k, Func<T, U, V> s) | |
{ | |
return m.SelectMany( | |
x => k(x).SelectMany( | |
y => s(x, y).ToMaybe())); | |
} | |
public static IEnumerable<T> ToList<T>(this T value) | |
{ | |
yield return value; | |
} | |
public static IEnumerable<U> SelectMany<T, U>(this IEnumerable<T> m, Func<T, IEnumerable<U>> k) | |
{ | |
foreach (var x in m) | |
foreach (var y in k(x)) | |
yield return y; | |
} | |
public static IEnumerable<V> SelectMany<T, U, V>(this IEnumerable<T> m, Func<T, IEnumerable<U>> k, Func<T, U, V> s) | |
{ | |
return m.SelectMany( | |
x => k(x).SelectMany( | |
y => s(x, y).ToList())); | |
} | |
public static K<T, Answer> ToContinuation<T, Answer>(this T value) | |
{ | |
return (Func<T, Answer> c) => c(value); | |
} | |
public static K<U, Answer> SelectMany<T, U, Answer>(this K<T, Answer> m, Func<T, K<U, Answer>> k) | |
{ | |
return (Func<U, Answer> c) => m((T x) => k(x)(c)); | |
} | |
public static K<V, Answer> SelectMany<T, U, V, Answer>(this K<T, Answer> m, | |
Func<T, K<U, Answer>> k, Func<T, U, V> s) | |
{ | |
return m.SelectMany( | |
x => k(x).SelectMany( | |
y => s(x, y).ToContinuation<V, Answer>())); | |
} | |
} | |
class Program | |
{ | |
static Identity<T> Unit<T>(T value) | |
{ | |
return new Identity<T>(value); | |
} | |
static Identity<U> Bind<T, U>(Identity<T> id, Func<T, Identity<U>> k) | |
{ | |
return k(id.Value); | |
} | |
static void Main(string[] args) | |
{ | |
//var r = Bind(Unit(5), x => | |
// Bind(Unit(6), y => | |
// Unit(x + y) | |
// ) | |
// ); | |
//var r = 5.ToIdentity().SelectMany( | |
// x => 6.ToIdentity().SelectMany( | |
// y => (x + y).ToIdentity())); | |
//var r = 5.ToIdentity() | |
// .SelectMany(x => 6.ToIdentity(), (x, y) => x + y); | |
//var r = from x in 5.ToIdentity() | |
// from y in 6.ToIdentity() | |
// select x + y; | |
//Console.WriteLine(r.Value); | |
//var r = 5.ToMaybe().SelectMany( | |
// x => Maybe<int>.Nothing.SelectMany( | |
// y => new Maybe<int>(x + y) | |
// ) | |
// ); | |
//var r = 5.ToMaybe() | |
// .SelectMany(x => Maybe<int>.Nothing, (x, y) => x + y); | |
//var r = from x in 5.ToMaybe() | |
// from y in Maybe<int>.Nothing | |
// select x + y; | |
//Console.WriteLine(r.HasValue ? r.Value.ToString() : "Nothing"); | |
//var r = from x in new[] { 0, 1, 2 } | |
// from y in new[] { 0, 1, 2 } | |
// select x + y; | |
//foreach (var i in r) | |
// Console.WriteLine(i); | |
//var r = 7.ToContinuation<int, string>() | |
// .SelectMany(x => 6.ToContinuation<int, string>() | |
// .SelectMany(y => (x + y).ToContinuation<int, string>())); | |
//var r = 7.ToContinuation<int, string>() | |
// .SelectMany(x => 6.ToContinuation<int, string>(), | |
// (x, y) => x + y); | |
var r = from x in 7.ToContinuation<int, string>() | |
from y in 6.ToContinuation<int, string>() | |
select x + y; | |
Console.WriteLine(r(z => z.ToString().Replace('1', 'a'))); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment