Skip to content

Instantly share code, notes, and snippets.

@ruxo
Last active February 5, 2023 08:27
Show Gist options
  • Select an option

  • Save ruxo/3df7e14d16fb9212cea9f99a340bc2b9 to your computer and use it in GitHub Desktop.

Select an option

Save ruxo/3df7e14d16fb9212cea9f99a340bc2b9 to your computer and use it in GitHub Desktop.
Simple number guessing game with Aff/Eff..
using LanguageExt;
using LanguageExt.Common;
using NetConsole = System.Console;
// ReSharper disable InconsistentNaming
namespace TestConsole;
public delegate Either<Error, A> IO<in Env, A>(Env env);
interface ConsoleIO
{
string ReadLine();
Unit Write(string text);
Unit WriteLine(string text);
}
interface HasConsole<RT> where RT : struct, HasConsole<RT>
{
Eff<RT, ConsoleIO> ConsoleEff { get; }
}
struct RealConsoleIO : ConsoleIO
{
public static readonly RealConsoleIO Default = new();
public string ReadLine() => NetConsole.ReadLine()!;
public Unit Write(string text) {
NetConsole.Write(text);
return Unit.Default;
}
public Unit WriteLine(string text) {
NetConsole.WriteLine(text);
return Unit.Default;
}
}
static class Console<RT> where RT : struct, HasConsole<RT>
{
public static Eff<RT, string> ReadLine() => default(RT).ConsoleEff.Map(rt => rt.ReadLine());
public static Eff<RT, Unit> Write(string text) => default(RT).ConsoleEff.Map(rt => rt.Write(text));
public static Eff<RT, Unit> WriteLine(string text) => default(RT).ConsoleEff.Map(rt => rt.WriteLine(text));
}
interface RandomEff
{
int Next(int max);
}
interface HasRandom<RT> where RT : struct, HasRandom<RT>
{
Eff<RT, RandomEff> RandomEff { get; }
}
readonly struct RealRandom : RandomEff
{
readonly Random r = new();
public static readonly RealRandom Default = new();
public RealRandom() { }
public int Next(int max) => r.Next(max);
}
static class Random<RT> where RT : struct, HasRandom<RT>
{
public static Eff<RT, int> Next(int max) => default(RT).RandomEff.Map(rt => rt.Next(max));
}
using LanguageExt;
using TestConsole;
using static LanguageExt.Prelude;
main<MyEnv>().Run(default).ThrowIfFail();
// ---------------------------------------- FUNCTIONS -------------------------------------------------
Eff<RT, Unit> main<RT>() where RT : struct, HasConsole<RT>, HasRandom<RT> =>
from target in Random<RT>.Next(100)
from ______ in play<RT>(target)
select unit;
Eff<RT, Unit> play<RT>(int target) where RT : struct, HasConsole<RT> =>
retry(from _______ in Console<RT>.Write("Guess: ")
from guess in Console<RT>.ReadLine().Map(int.Parse)
from correct in showResult<RT>(target, guess)
select correct);
Eff<RT, Unit> showResult<RT>(int target, int guess) where RT : struct, HasConsole<RT> =>
target == guess
? Console<RT>.WriteLine($"Congrat, it's {guess}!")
: guess < target
? Console<RT>.WriteLine("Too small").Filter(_ => false)
: Console<RT>.WriteLine("Too big").Filter(_ => false);
struct MyEnv : HasConsole<MyEnv>, HasRandom<MyEnv>
{
public Eff<MyEnv, ConsoleIO> ConsoleEff => Eff<MyEnv, ConsoleIO>(static _ => RealConsoleIO.Default);
public Eff<MyEnv, RandomEff> RandomEff => Eff<MyEnv, RandomEff>(static _ => RealRandom.Default);
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LanguageExt.Core" Version="4.4.0" />
</ItemGroup>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment