Skip to content

Instantly share code, notes, and snippets.

@palladin
Created July 12, 2023 19:54
Show Gist options
  • Save palladin/e96b545dbbb1b8d80f2d325fd53be0dc to your computer and use it in GitHub Desktop.
Save palladin/e96b545dbbb1b8d80f2d325fd53be0dc to your computer and use it in GitHub Desktop.
Eff with static abstract members
using Nessos.Effects;
using Nessos.Effects.Handlers;
public class ConsolePrintEffect : Effect
{
public string? Message { init; get; }
}
public class ConsoleReadEffect : Effect<string?>
{
}
public class ConsoleOps
{
public static readonly ConsoleOps Ops = new ConsoleOps();
public ConsolePrintEffect Print(string message) => new ConsolePrintEffect { Message = message };
public ConsoleReadEffect Read() => new ConsoleReadEffect();
}
public interface IConsoleEffect<T> where T : IConsoleEffect<T>
{
public static abstract ConsoleOps Console { get; }
}
public class EffectCtxHandler : EffectHandler
{
public override async ValueTask Handle<TResult>(EffectAwaiter<TResult> awaiter)
{
switch (awaiter)
{
case EffectAwaiter { Effect: ConsolePrintEffect printEffect } awtr:
System.Console.Write(printEffect.Message);
awtr.SetResult();
break;
case EffectAwaiter<string?> { Effect: ConsoleReadEffect _ } awtr:
string? message = System.Console.ReadLine();
awtr.SetResult(message);
break;
default:
throw new NotSupportedException(awaiter.Effect.GetType().Name);
};
}
}
public struct Ctx : IConsoleEffect<Ctx>
{
public static ConsoleOps Console => ConsoleOps.Ops;
}
public class Program
{
static async Eff Test<Ctx>()
where Ctx : IConsoleEffect<Ctx>
{
await Ctx.Console.Print("Enter your name: ");
var message = await Ctx.Console.Read();
await Ctx.Console.Print($"Hello, {message}!\n");
}
public static async Task Main()
{
await Test<Ctx>().Run(new EffectCtxHandler());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment