Skip to content

Instantly share code, notes, and snippets.

@bleis-tift
Created December 10, 2015 05:34
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 bleis-tift/dacab83d9a6aafa15e8e to your computer and use it in GitHub Desktop.
Save bleis-tift/dacab83d9a6aafa15e8e to your computer and use it in GitHub Desktop.
型だけ合わせてみたC#でStateモナド
using System;
namespace StateMonad
{
// sample:
// var proc =
// from initVal in State.Get<int>()
// let x = initVal + 10
// from _ in State.Put(x * 2)
// select (x / 2).ToString();
// var result = proc.Run(100);
// Console.WriteLine("Result Value: " + result.Value);
// Console.WriteLine("Last State: " + result.State);
public class State<TState, T>
{
public class Data
{
public readonly T Value;
public readonly TState State;
public Data(T value, TState state)
{
this.Value = value;
this.State = state;
}
}
internal readonly Func<TState, Data> RunState;
public State(Func<TState, Data> runState)
{
this.RunState = runState;
}
public State<TState, U> Select<U>(Func<T, U> f)
{
return new State<TState, U>(state =>
{
var res = this.RunState(state);
var value = res.Value;
var newState = res.State;
return new State<TState, U>.Data(f(value), newState);
});
}
public State<TState, U> SelectMany<U>(Func<T, State<TState, U>> f)
{
return new State<TState, U>(state =>
{
var res = this.RunState(state);
var value = res.Value;
var newState = res.State;
return f(value).RunState(newState);
});
}
public State<TState, V> SelectMany<U, V>(Func<T, State<TState, U>> f, Func<T, U, V> g)
{
return new State<TState, V>(state =>
{
var res = this.RunState(state);
var value = res.Value;
var newState = res.State;
var newRes = f(value).RunState(newState);
return new State<TState, V>.Data(g(value, newRes.Value), newRes.State);
});
}
public Data Run(TState initialState)
{
return this.RunState(initialState);
}
}
public enum Unit { _ }
public static class State
{
public static State<T, T> Get<T>()
{
return new State<T, T>(state => new State<T, T>.Data(state, state));
}
public static State<TState, Unit> Put<TState>(TState state)
{
return new State<TState, Unit>(_ => new State<TState, Unit>.Data(Unit._, state));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment