Skip to content

Instantly share code, notes, and snippets.

@rarous
Last active December 16, 2015 01:29
Show Gist options
  • Save rarous/5355792 to your computer and use it in GitHub Desktop.
Save rarous/5355792 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
public interface Maybe<T> { }
public class Nothing<T> : Maybe<T> { }
public class Just<T> : Maybe<T> {
public T Value { get; private set; }
public Just(T value) {
Value = value;
}
}
public static class MaybeExtensions {
public static Maybe<T> ToMaybe<T>(this T value) {
return value == null ? new Nothing<T>() : (Maybe<T>)new Just<T>(value);
}
public static Maybe<T> ToMaybe<T>(this Nullable<T> value) where T : struct {
return value.HasValue ? (Maybe<T>)new Just<T>(value.Value) : new Nothing<T>();
}
public static Maybe<T[]> ToMaybeArray<T>(this IEnumerable<T> enumerable) {
return enumerable.Any() ? enumerable.ToArray().ToMaybe() : new Nothing<T[]>();
}
public static Maybe<IEnumerable<T>> ToMaybeEnumerable<T>(this IEnumerable<T> enumerable) {
return enumerable.Any() ? enumerable.ToMaybe() : new Nothing<IEnumerable<T>>();
}
public static Maybe<T> MaybeFirst<T>(this IEnumerable<T> xs) {
return xs.Any() ? new Just<T>(xs.First()) : (Maybe<T>)new Nothing<T>();
}
public static Maybe<T> MaybeFirst<T>(this IEnumerable<Maybe<T>> xs) {
var some = xs.OfType<Just<T>>().Cast<Maybe<T>>();
return some.Any() ? some.First() : new Nothing<T>();
}
public static Maybe<T> MaybeFirst<T>(this IEnumerable<T> xs, Func<T, bool> predicate) {
return xs.Any(predicate) ? new Just<T>(xs.First(predicate)) : (Maybe<T>)new Nothing<T>();
}
public static Maybe<T> MaybeLast<T>(this IEnumerable<T> xs, Func<T, bool> predicate) {
return xs.Any(predicate) ? new Just<T>(xs.Last(predicate)) : (Maybe<T>)new Nothing<T>();
}
public static Maybe<T> MaybeLast<T>(this IEnumerable<Maybe<T>> xs) {
var some = xs.OfType<Just<T>>().Cast<Maybe<T>>();
return some.Any() ? some.Last() : new Nothing<T>();
}
public static Maybe<B> Bind<A, B>(this Maybe<A> a, Func<A, Maybe<B>> func) {
var justa = a as Just<A>;
return justa == null ? new Nothing<B>() : func(justa.Value);
}
public static Maybe<C> SelectMany<A, B, C>(this Maybe<A> a, Func<A, Maybe<B>> func, Func<A, B, C> select) {
return a.Bind(aval => func(aval).Bind(bval => select(aval, bval).ToMaybe()));
}
public static Maybe<B> Select<A, B>(this Maybe<A> a, Func<A, Maybe<B>> func) {
return a.Bind(func);
}
public static Maybe<T> Where<T>(this Maybe<T> a, Func<T, bool> predicate) {
return a.Bind(x => predicate(x) ? (Maybe<T>)x : new Nothing<T>());
}
public static Maybe<T> Or<T>(this Maybe<T> a, Maybe<T> b) {
return a is Nothing<T> ? b : a;
}
public static R Match<T, R>(this Maybe<T> a, Func<T, R> some, Func<R> none) {
var justa = a as Just<T>;
return justa == null ? none() : some(justa.Value);
}
public static Maybe<T> Do<T>(this Maybe<T> a, Action<T> some, Action none) {
var justa = a as Just<T>;
if (justa == null) none();
else some(justa.Value);
return a;
}
public static Nullable<T> ToNullable<T>(this Maybe<T> maybe) where T : struct {
return maybe.Match(x => (Nullable<T>)x, () => null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment