Skip to content

Instantly share code, notes, and snippets.

@loosechainsaw
Created October 16, 2014 11:12
Show Gist options
  • Save loosechainsaw/5b1286043c90fa1e428a to your computer and use it in GitHub Desktop.
Save loosechainsaw/5b1286043c90fa1e428a to your computer and use it in GitHub Desktop.
IO Monad
using NUnit.Framework;
using System;
namespace Monads
{
public class Unit{
private Unit(){
}
public static Unit Instance(){
return value.Value;
}
private static Lazy<Unit> value = new Lazy<Unit>(() => new Unit() );
}
public interface IIO<out T>{
T PerformUnsafeIO();
}
public class IO<T> : IIO<T>{
public IO(Func<T> function){
this.function = function;
}
public T PerformUnsafeIO(){
return function();
}
private Func<T> function;
}
public static class IOExtensions{
public static IIO<T> Unit<T>(this Func<T> f){
return new IO<T>(f);
}
public static IIO<U> Select<T,U>(this IIO<T> io, Func<T,U> map){
return new IO<U>(() => map(io.PerformUnsafeIO()));
}
public static IIO<U> SelectMany<T,U>(this IIO<T> io, Func<T, IIO<U>> mapMany){
return new IO<U>(() =>
{
return mapMany(io.PerformUnsafeIO()).PerformUnsafeIO();
});
}
public static IIO<V> SelectMany<T,U,V>(this IIO<T> io, Func<T, IIO<U>> mapMany, Func<T,U,V> map){
return new IO<V>(() =>
{
var a = io.PerformUnsafeIO();
var b = mapMany(a).PerformUnsafeIO();
return map(a,b);
});
}
}
public interface IConsoleWriter : IIO<Unit>{
}
public class ConsoleWriter : IConsoleWriter{
public ConsoleWriter(string text){
this.text = text;
}
public Unit PerformUnsafeIO()
{
Console.WriteLine(text);
return Unit.Instance();
}
private string text;
}
[TestFixture]
public class MonadTests
{
public IIO<Unit> WriteWorld(Unit unit){
return new ConsoleWriter("World");
}
[Test]
public void IOMonadSample()
{
var a = new ConsoleWriter("Hello").SelectMany(WriteWorld).PerformUnsafeIO();
var r = from x in new ConsoleWriter("Hello")
from z in WriteWorld(x)
select z;
r.PerformUnsafeIO();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment