Last active
June 13, 2024 12:23
-
-
Save atifaziz/4a0438946e6002148001a98804f93b3d to your computer and use it in GitHub Desktop.
Interact Monad, derived from https://fssnip.net/8ay (Interactive computation that asks the user questions)
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
// Interact Monad, derived from https://fssnip.net/8ay (by Tomas Petricek) | |
// Interactive computation that asks the user questions | |
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
static Interactive<Color> GetColor() => new WhatColor<Color>(Interactive.Return); | |
static Interactive<int> GetNumber() => new WhatNumber<int>(Interactive.Return); | |
var demo = | |
from c1 in GetColor() | |
from c2 in GetColor() | |
from n in GetNumber() | |
select Enumerable.Repeat(c1 == c2, n); | |
var flags = Run(demo); | |
Console.WriteLine($"Got {string.Join(", ", flags)}"); | |
static T Run<T>(Interactive<T> c) | |
{ | |
switch (c) | |
{ | |
case Done<T>(var r): | |
return r; | |
case WhatNumber<T>(var f): | |
var input = Console.ReadLine(); | |
return Run(f(int.Parse(input))); | |
case WhatColor<T>(var f): | |
return Console.ReadLine() switch | |
{ | |
"pink" => Run(f(Color.Pink)), | |
"purple" => Run(f(Color.Purple)), | |
_ => throw new("Wrong input."), | |
}; | |
default: throw new UnreachableException(); | |
} | |
} | |
abstract record Interactive<T>; | |
sealed record Done<T>(T Result) : Interactive<T>; | |
sealed record WhatNumber<T>(Func<int, Interactive<T>> Cont) : Interactive<T>; | |
sealed record WhatColor<T>(Func<Color, Interactive<T>> Cont) : Interactive<T>; | |
enum Color { Pink, Purple } | |
static class Interactive | |
{ | |
public static Interactive<T> Return<T>(T result) => new Done<T>(result); | |
public static Interactive<U> Bind<T, U>(this Interactive<T> comp, | |
Func<T, Interactive<U>> f) => | |
comp switch | |
{ | |
Done<T>(var v) => f(v), | |
WhatColor<T>(var g) => new WhatColor<U>(c => g(c).Bind(f)), | |
WhatNumber<T>(var g) => new WhatNumber<U>(n => g(n).Bind(f)), | |
}; | |
public static Interactive<U> Select<T, U>(this Interactive<T> comp, Func<T, U> f) => | |
comp.Bind(e => Return(f(e))); | |
public static Interactive<V> SelectMany<T, U, V>(this Interactive<T> comp, | |
Func<T, Interactive<U>> f, | |
Func<T, U, V> g) => | |
comp.Bind(a => from b in f(a) select g(a, b)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment