Last active
December 19, 2019 13:01
-
-
Save Pzixel/05d6fc18f389149e64995b148147345e 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; | |
namespace ConsoleApp28 | |
{ | |
public readonly struct Unit | |
{ | |
public static Unit Instance { get; } = new Unit(); | |
} | |
public class State<S, A> | |
{ | |
public Func<S, (A, S)> Run { get; } | |
public State(Func<S, (A, S)> run) | |
{ | |
Run = run; | |
} | |
public static State<S, A> Return(A a) => new State<S, A>(s => (a, s)); | |
public State<S, B> Bind<B>(Func<A, State<S, B>> g) => new State<S, B>(s1 => | |
{ | |
var (a, s2) = Run(s1); | |
return g(a).Run(s2); | |
}); | |
} | |
public static class State | |
{ | |
public static State<S, S> Get<S>() => new State<S, S>(s => (s, s)); | |
public static State<S, Unit> Set<S>(S s) => new State<S, Unit>(_ => (Unit.Instance, s)); | |
} | |
public static class XState | |
{ | |
public static State<S, B> Select<S, A, B>(this State<S, A> value, Func<A, B> map) => | |
value.Bind(a => State<S, B>.Return(map(a))); | |
public static State<S, TResult> SelectMany<S, A, B, TResult>(this State<S, A> value, Func<A, State<S, B>> bind, Func<A, B, TResult> project) => | |
value.Bind(a => bind(a).Bind(b => State<S, TResult>.Return(project(a, b)))); | |
} | |
class Program | |
{ | |
static State<int, Unit> Foo(int a) => | |
from x in State.Get<int>() | |
let valueToAdd = a > 0 ? 1 : a == 0 ? 2 : 3 | |
from _ in State.Set(x + valueToAdd) | |
select Unit.Instance; | |
static State<string, Unit> ConcatStates(State<string, Unit> a, State<string, Unit> b) => | |
from __ in a | |
from aValue in State.Get<string>() | |
from _ in b | |
from bValue in State.Get<string>() | |
from ___ in State.Set<string>(aValue + bValue) | |
select Unit.Instance; | |
static void Main(string[] args) | |
{ | |
var initial = State<int, Unit>.Return(Unit.Instance); | |
var next = Foo(0); | |
var next2 = Foo(-1); | |
Console.WriteLine(next.Bind(_ => next2).Run(100)); | |
var a = State.Set("Hello "); | |
var b = State.Set("World!"); | |
Console.WriteLine(ConcatStates(a, b).Run("")); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment