Skip to content

Instantly share code, notes, and snippets.

@atifaziz
Last active January 18, 2017 07:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atifaziz/ed1c5e6d5ed231044aaddef8e8cdec59 to your computer and use it in GitHub Desktop.
Save atifaziz/ed1c5e6d5ed231044aaddef8e8cdec59 to your computer and use it in GitHub Desktop.
Experiments in IO monad (C#)
using System;
using System.Runtime.InteropServices;
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
// ReSharper disable PartialTypeWithSinglePart
sealed partial class IO<T>
{
readonly Func<T> _func;
public IO(Func<T> func) { _func = func; }
public T Run() => _func();
}
static partial class IO
{
public static IO<T> Create<T>(Func<T> func) =>
new IO<T>(func);
public static IO<U> Bind<T, U>(this IO<T> io, Func<T, IO<U>> f) =>
Create(() => f(io.Run()).Run());
public static IO<U> Select<T, U>(this IO<T> io, Func<T, U> selector) =>
io.Bind(x => Create(() => selector(x)));
public static IO<V> SelectMany<T, U, V>(this IO<T> first, Func<T, IO<U>> secondSelector, Func<T, U, V> resultSelector) =>
first.Bind(x => secondSelector(x).Bind(y => Create(() => resultSelector(x, y))));
public static IO<string> ReadLine() =>
Create(() => Console.ReadLine());
public static IO<Unit> WriteLine(string s) =>
Create(() => { Console.WriteLine(s); return new Unit(); });
}
static class Program
{
static void Main() =>
Wain().Run();
static IO<Unit> Wain() =>
from _1 in IO.WriteLine("Enter X: ")
from xx in IO.ReadLine()
from _2 in IO.WriteLine($"X is {xx}. Now enter Y: ")
from yy in IO.ReadLine()
from _3 in IO.WriteLine($"{xx} + {yy} = {int.Parse(xx) + int.Parse(yy)}")
select new Unit();
}
/// <summary>
/// A type that indicates the absence of a specific value. It has only a
/// single value, which acts as a placeholder when no other value exists or
/// is needed.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct Unit : IEquatable<Unit>
{
public static bool operator ==(Unit a, Unit b) => true;
public static bool operator !=(Unit a, Unit b) => false;
public bool Equals(Unit other) => true;
public override bool Equals(object obj) => obj is Unit;
public override int GetHashCode() => 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment