Created
July 25, 2018 08:54
-
-
Save masaeedu/ba0cde72ba513080c660f390924169ac to your computer and use it in GitHub Desktop.
This file contains hidden or 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; | |
| using System.Threading.Tasks; | |
| namespace tmp.zNpqzfT0PE | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| var job = ChangeForegroundColor(ConsoleColor.Blue) | |
| .BindDisp(_ => Print("Blue prompt says: 'please enter something in red, I will echo it back in green'").LiftDisp()) | |
| .BindDisp(_ => ChangeForegroundColor(ConsoleColor.Red)) | |
| .BindDisp(_ => ReadInput.LiftDisp()) | |
| .BindDisp(input => ChangeForegroundColor(ConsoleColor.Green).MapDisp(_ => input)) | |
| .BindDisp(input => Print(input).LiftDisp()); | |
| job.BindCont(result => result.Cleanup) | |
| .Run(_ => { }); | |
| // We should be back to black here | |
| Console.WriteLine("This text in boring black :("); | |
| } | |
| public static Cont<Unit> Print(string message) | |
| => new Cont<Unit>(cb => | |
| { | |
| Console.WriteLine(message); | |
| cb(Unit.Only); | |
| }); | |
| public static Cont<String> ReadInput { get; } | |
| = new Cont<string>(cb => | |
| { | |
| var result = Console.ReadLine(); | |
| cb(result); | |
| }); | |
| public static Cont<Acq<ConsoleColor>> ChangeForegroundColor(ConsoleColor color) | |
| { | |
| return Disposable.Acquire<ConsoleColor>( | |
| new Cont<ConsoleColor>(cb => | |
| { | |
| var oldColor = Console.ForegroundColor; | |
| // Console.WriteLine($"Changing color from {oldColor} to {color}"); | |
| Console.ForegroundColor = color; | |
| cb(oldColor); | |
| }), | |
| oldColor => new Cont<Unit>(cb => | |
| { | |
| // Console.WriteLine($"Reverting color to {oldColor}"); | |
| Console.ForegroundColor = oldColor; | |
| cb(Unit.Only); | |
| }) | |
| ); | |
| } | |
| } | |
| public sealed class Unit | |
| { | |
| private Unit() { } | |
| public static Unit Only { get; } = new Unit(); | |
| } | |
| public class Acq<V> | |
| { | |
| public V Value { get; } | |
| public Cont<Unit> Cleanup { get; } | |
| public Acq(V value, Cont<Unit> cleanup) | |
| { | |
| Value = value; | |
| Cleanup = cleanup; | |
| } | |
| } | |
| public static class Disposable | |
| { | |
| public static Cont<Acq<V>> LiftDisp<V>(this Cont<V> c) | |
| => c.MapCont(v => new Acq<V>(v, Cont.PureCont(Unit.Only))); | |
| public static Cont<Acq<V>> PureDisp<V>(V v) | |
| => Cont.PureCont(new Acq<V>(v, Cont.PureCont(Unit.Only))); | |
| public static Cont<Acq<B>> BindDisp<A, B>(this Cont<Acq<A>> a, Func<A, Cont<Acq<B>>> f) | |
| { | |
| return a.BindCont(acqA => | |
| { | |
| var va = acqA.Value; | |
| var cleanupA = acqA.Cleanup; | |
| return f(va) | |
| .MapCont(b => new Acq<B>(b.Value, b.Cleanup.BindCont(_ => cleanupA))); | |
| }); | |
| } | |
| public static Cont<Acq<B>> MapDisp<A, B>(this Cont<Acq<A>> a, Func<A, B> f) | |
| => a.BindDisp(v => PureDisp(f(v))); | |
| public static Cont<Acq<A>> Acquire<A>(Cont<A> run, Func<A, Cont<Unit>> cleanup) | |
| => run.MapCont(a => new Acq<A>(a, cleanup(a))); | |
| } | |
| public class Cont<A> | |
| { | |
| public Action<Action<A>> Run { get; } | |
| public Cont(Action<Action<A>> run) | |
| { | |
| Run = run; | |
| } | |
| } | |
| public static class Cont | |
| { | |
| public static Cont<A> New<A>(Action<Action<A>> run) | |
| => new Cont<A>(run); | |
| public static Cont<A> PureCont<A>(A a) | |
| => new Cont<A>(cb => cb(a)); | |
| public static Cont<B> BindCont<A, B>(this Cont<A> a, Func<A, Cont<B>> f) | |
| => new Cont<B>(cb => a.Run(v => f(v).Run(cb))); | |
| public static Cont<B> MapCont<A, B>(this Cont<A> a, Func<A, B> f) | |
| => a.BindCont(v => PureCont(f(v))); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment