Last active
December 16, 2015 01:29
-
-
Save rarous/5355792 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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