Created
November 5, 2012 09:23
-
-
Save bradphelan/4016243 to your computer and use it in GitHub Desktop.
Maybe
This file contains hidden or 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; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace FunctionalExtensions | |
{ | |
#region Maybe | |
public delegate Maybe<TOutput> Converter<in TInput, out TOutput>(TInput input); | |
public delegate TOutput ElseDelegate<out TOutput>(); | |
public delegate Maybe<TOutput> ElseDelegate2<out TOutput>(); | |
public interface Maybe<out TResult> | |
{ | |
Maybe<B> Bind<B>(Converter<TResult, B> f); | |
TResult Value(); | |
bool IsSome(); | |
} | |
public static class Maybe | |
{ | |
public static Maybe<T> None<T>(){ | |
return new NoneImpl<T>(); | |
} | |
} | |
public interface None<out TResult> : Maybe<TResult> | |
{ | |
} | |
public interface Some<out TResult> : Maybe<TResult> | |
{ | |
} | |
public static class MaybeMixins | |
{ | |
public static T Else<T>(this Maybe<T> This, T defaultValue){ | |
if (This.IsSome()) | |
{ | |
return This.Value(); | |
} | |
else | |
{ | |
return defaultValue; | |
} | |
} | |
public static Maybe<T> Else<T>(this Maybe<T> This, ElseDelegate<T> del){ | |
if (This.IsSome()) | |
{ | |
return This; | |
} | |
else | |
{ | |
return del().ToMaybe(); | |
} | |
} | |
public static Maybe<T> Else<T>(this Maybe<T> This, ElseDelegate2<T> del){ | |
if (This.IsSome()) | |
{ | |
return This; | |
} | |
else | |
{ | |
return del(); | |
} | |
} | |
public static Maybe<TResult> Select<TSource, TResult>(this Maybe<TSource> m, Func<TSource, TResult> f) | |
{ | |
return m.Bind(x => f(x).ToMaybe()); | |
} | |
public static Maybe<TResult> SelectMany<TSource, TResult>(this Maybe<TSource> m, Func<TSource, TResult> f) | |
{ | |
return m.Bind(x => f(x).ToMaybe()); | |
} | |
public static Maybe<TResult> SelectMany<TSource, TMaybe, TResult>(this Maybe<TSource> m, Func<TSource, Maybe<TMaybe>> f, Func<TSource, TMaybe, TResult> g) | |
{ | |
return m.Bind(x => f(x).Bind(y => g(x, y).ToMaybe())); | |
} | |
public static Maybe<T> Where<T>(this Maybe<T> This, Predicate<T> p){ | |
return This.Bind((x) => (p(x) ? x.ToMaybe() : Maybe.None<T>())); | |
} | |
public static Maybe<TSource> ToMaybe<TSource>(this TSource This) | |
{ | |
if (This == null) | |
{ | |
return new NoneImpl<TSource>(); | |
} | |
else | |
{ | |
return new SomeImpl<TSource>(This); | |
} | |
} | |
} | |
internal class NoneImpl<TResult> : None<TResult>{ | |
public NoneImpl() | |
{} | |
public virtual bool IsSome() { return false; } | |
public Maybe<TOutput> Bind<TOutput>(Converter<TResult, TOutput> f) | |
{ | |
return new NoneImpl<TOutput>(); | |
} | |
public virtual TResult Value() | |
{ | |
throw new IndexOutOfRangeException("None has no value"); | |
} | |
} | |
internal class SomeImpl<TResult> : Some<TResult> | |
{ | |
private TResult _Value; | |
public SomeImpl(TResult value) | |
{ | |
_Value = value; | |
} | |
public virtual bool IsSome() { return true; } | |
public Maybe<TOutput> Bind<TOutput>(Converter<TResult, TOutput> f) | |
{ | |
return f(_Value); | |
} | |
public virtual TResult Value() | |
{ | |
return this._Value; | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment