Skip to content

Instantly share code, notes, and snippets.

@dtchepak
Created March 28, 2013 12:46
Show Gist options
  • Save dtchepak/5262838 to your computer and use it in GitHub Desktop.
Save dtchepak/5262838 to your computer and use it in GitHub Desktop.
Messing around with an IO type in C#
using System;
namespace Workshop.Terminal
{
// Meh, close enough
public sealed class Unit { }
public sealed class IO<T>
{
private readonly Func<T> ioAction;
public IO(Func<T> ioAction) { this.ioAction = ioAction; }
public IO<TNext> Then<TNext>(IO<TNext> next)
{
return new IO<TNext>(() => {
ioAction();
return next.ioAction();
});
}
public IO<TNext> Then<TNext>(Func<T, IO<TNext>> useValue)
{
return new IO<TNext>(() => {
var value = ioAction();
var nextIO = useValue(value);
return nextIO.ioAction();
});
}
public IO<TB> SelectMany<TA, TB>(Func<T, IO<TA>> useValue, Func<T, TA, TB> selector)
{
return new IO<TB>(() => {
var value = ioAction();
var nextIO = useValue(value);
var nextValue = nextIO.ioAction();
return selector(value, nextValue);
});
}
public IO<TNext> Select<TNext>(Func<T, TNext> selector)
{
return new IO<TNext>(() => selector(ioAction()));
}
// DON'T CALL THIS!
public T UnsafePerformIO() { return ioAction(); }
}
public static class IO
{
private static Random random = new Random();
public static IO<Unit> WriteLine(string s)
{
return new IO<Unit>(() => { Console.WriteLine(s); return new Unit(); });
}
public static IO<string> ReadLine() { return new IO<string>(Console.ReadLine); }
public static IO<int> Random(int min, int max)
{
return new IO<int>(() => random.Next(min, max));
}
}
class Program
{
public static void SideEffecty()
{
Console.WriteLine("Hi, I'm C#. What's your name?");
var name = Console.ReadLine();
Console.WriteLine("Nice to meet you " + name);
}
public static Action NotSoSideEffecty()
{
return () =>
{
Console.WriteLine("Hi, I'm C#. What's your name?");
var name = Console.ReadLine();
Console.WriteLine("Nice to meet you " + name);
};
}
public static IO<Unit> GuessNumber(int i)
{
return IO.ReadLine()
.Select(int.Parse) // should use Option type here for error handling
.Then(guess =>
{
if (guess > i)
{
return IO.WriteLine("Too high!").Then(GuessNumber(i));
}
else if (guess < i)
{
return IO.WriteLine("Too low!").Then(GuessNumber(i));
}
return IO.WriteLine("You got it!");
});
}
static void Main(string[] args)
{
var program =
from a in IO.WriteLine("Hi, I'm C#. What's your name?")
from name in IO.ReadLine()
from b in IO.WriteLine("Nice to meet you " + name +
". I'm thinking of a number between 1 and 10. Try and guess it!")
from rand in IO.Random(1,10)
from c in GuessNumber(rand)
select new Unit();
program.UnsafePerformIO();
Console.ReadLine();
}
}
}
@dtchepak
Copy link
Author

dtchepak commented Apr 5, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment