Skip to content

Instantly share code, notes, and snippets.

@dtchepak
Created April 7, 2013 11:28
Show Gist options
  • Save dtchepak/5330109 to your computer and use it in GitHub Desktop.
Save dtchepak/5330109 to your computer and use it in GitHub Desktop.
I have no idea what I'm doing.
public class STRunner {
private class STToken { }
public A RunST<A>(ISTScope<A> scope) {
return scope.Get<STToken>().UnsafeRun(new STToken());
}
}
public interface ISTScope<A> {
ST<S, A> Get<S>();
}
public class ST<S, A> {
private readonly Func<S, Tuple<A, S>> _mutableOp;
internal A UnsafeRun(S state) { return _mutableOp(state).Item1; }
public ST(Func<S,Tuple<A,S>> mutableOp) {
_mutableOp = mutableOp;
}
public ST<S, C> SelectMany<B,C>(Func<A, ST<S, B>> f, Func<A, B, C> selector) {
return new ST<S, C>(s => {
var stateAndA = _mutableOp(s);
var stB = f(stateAndA.Item1);
var stateAndB = stB._mutableOp(stateAndA.Item2);
return Tuple.Create(selector(stateAndA.Item1, stateAndB.Item1), stateAndB.Item2);
});
}
}
public class STRef<S, A> {
private A value;
public STRef(A a) { value = a; }
public ST<S, A> Read() {
return new ST<S, A>(s => Tuple.Create(value, s));
}
public ST<S, Unit> Write(A a) {
return new ST<S, Unit>(s => {
value = a;
return Tuple.Create(new Unit(), s);
});
}
}
public class STScope : ISTScope<int> {
public ST<S, int> Get<S>() {
var v = new STRef<S, int>(5);
return
from a in v.Read() // a = 5
from b in v.Write(a*10) // v <- 50
from c in v.Read() // c = 50
select a + c; // return: 55
}
}
[Test]
public void TestST() {
var result = new STRunner().RunST(new STScope());
result.ShouldBe(55);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment