Skip to content

Instantly share code, notes, and snippets.

@amaya382
Last active January 7, 2019 05:47
Show Gist options
  • Save amaya382/4caf1768bd4738fa9a65 to your computer and use it in GitHub Desktop.
Save amaya382/4caf1768bd4738fa9a65 to your computer and use it in GitHub Desktop.
実用重視のOptionMonad"""モドキ""" in C#
//直和を表現しきれない点を気にしたら負け
public interface IOption<out T> : IEnumerable<T>
{
bool HasValue { get; }//== this.Any()
}
sealed public class Some<T> : IOption<T>
{
private readonly T val;
public bool HasValue { get { return true; } }
public Some(T v) {
val = v;
}
public IEnumerator<T> GetEnumerator() {
yield return val;
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
sealed public class None<T> : IOption<T>
{
public bool HasValue { get { return false; } }
public None() { }
public IEnumerator<T> GetEnumerator() {
yield break;
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
static public class Option
{
static public Some<T> Some<T>(T v) {
return new Some<T>(v);
}
static public None<T> None<T>() {
return new None<T>();
}
static public IOption<T> Return<T>(T v) {
if (v != null)
return new Some<T>(v);
else
return new None<T>();
}
static public IOption<U> Bind<T, U>(this IOption<T> _, Func<T, IOption<U>> f) {
return _.HasValue ?
f(_.First()) :
Option.None<U>();
}
static public IOption<T> ToOption<T>(this IEnumerable<T> _) {
if (_.Any())
return Option.Some<T>(_.First());
else
return Option.None<T>();
}
static public U Match<T, U>(this IOption<T> _, Func<T, U> Some, Func<U> None) {
return _.HasValue ?
Some(_.First()) :
None();
}
static public void Match<T>(this IOption<T> _, Action<T> Some, Action None) {
if (_.HasValue)
Some(_.First());
else
None();
}
}
var x = 10;
var m = Option.Return<int>(x);
Func<int, IOption<int>> f = v => Option.Some(v + 1);
Func<int, IOption<int>> g = v => Option.Some(v * 3);
//左恒等性(m00 == m01)
var m00 = Option.Return(x).Bind(f);
var m01 = f(x);
//右恒等性(m10 == m11)
var m10 = m.Bind(Option.Return);
var m11 = m;
//結合則(m21 == m21)
var m20 = m.Bind(f).Bind(g);
var m21 = m.Bind(v => f(v).Bind(g));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment