Skip to content

Instantly share code, notes, and snippets.

@masaru-b-cl
Created November 13, 2012 06:01
Show Gist options
  • Save masaru-b-cl/4064229 to your computer and use it in GitHub Desktop.
Save masaru-b-cl/4064229 to your computer and use it in GitHub Desktop.
「モナドの脅威」のコード写経
// 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