型構成子とか関数の拡張が自動化できればよかったけれど、とりあえずごりごり記述。
確かに使う側での副作用はなさそう。
// Haskell の >>= がなんて呼ばれているかわからない…orz。とりあえず束縛。
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
var result1 =
new Maybe<string[]>(new string[] { "012", "345", null, "678" })
.Bind(ss => ss.Skip(1))
.Bind(ss => ss.Skip(1).ElementAt(0))
.Bind(s => Regex.Match(s, "[0-3]+"))
.Bind(m => m.Value);
Console.WriteLine("result1 = " + result1.Apply());
// result1 =
var result2 =
new Maybe<string[]>(new string[] { "012", "345", "3", "678" })
.Bind(ss => ss.Skip(1))
.Bind(ss => ss.Skip(1).ElementAt(0))
.Bind(s => Regex.Match(s, "[0-3]+"))
.Bind(m => m.Value);
Console.WriteLine("result2 = " + result2.Apply());
// result2 = 3
var result3 =
new State<string, string>("123456789")
.Bind<string, int>(t => new Tuple<string, int>(t.State, t.State.Length))
.Bind<int, string>(t => new Tuple<int, string>(t.State, t.State.ToString()))
.Bind<string, string>(t => new Tuple<string, string>(t.State, t.State + "010101"));
Console.WriteLine("result3 = " + result3.Apply());
// result3 = 9010101
Console.ReadLine();
}
}
// Maybe モナド?
public class Maybe<T>
where T : class
{
private Func<T> func;
public Maybe(T value)
{
this.func = new Func<T>(() => value);
}
public Maybe(Func<T> func)
{
if (func == null) throw new ArgumentNullException("func");
this.func = func;
}
public Maybe<S> Bind<S>(Func<T, S> func)
where S : class
{
if (func == null) throw new ArgumentNullException("func");
return new Maybe<S>(new Func<S>(() => { var x = this.func(); return x == null ? null : func(x); }));
}
public T Apply()
{
return this.func();
}
}
// State モナド?
public class State<V1, S1>
{
private Func<V1, Tuple<V1, S1>> func;
public State(S1 s)
{
this.func = new Func<V1, Tuple<V1, S1>>(value => new Tuple<V1, S1>(value, s));
}
public State(Func<V1, Tuple<V1, S1>> func)
{
if (func == null) throw new ArgumentNullException("func");
this.func = func;
}
public State<V2, S2> Bind<V2, S2>(Func<Tuple<V1, S1>, Tuple<V2, S2>> func)
{
if (func == null) throw new ArgumentNullException("func");
return new State<V2, S2>(
new Func<V2, Tuple<V2, S2>>(value => { var t = func(this.func(default(V1))); return new Tuple<V2, S2>(t.Value, t.State); }));
}
public S1 Apply()
{
return this.func(default(V1)).State;
}
}
// C# にも Tuple 欲しいかも。
public struct Tuple<V1, S1>
{
private V1 value;
private S1 state;
public Tuple(V1 value, S1 state)
{
this.value = value;
this.state = state;
}
public V1 Value { get { return this.value; } set { this.value = value; } }
public S1 State { get { return this.state; } set { this.state = value; } }
}
0 件のコメント:
コメントを投稿