我正在使用option<`a`>
Petricek 书(真实世界函数式编程)中 F# monad 的 C# 实现:
internal enum OptionType { Some, None }
internal abstract class Option<T>
{
private readonly OptionType tag;
protected Option(OptionType tag)
{
this.tag = tag;
}
public OptionType Tag
{
get { return this.tag; }
}
public bool MatchNone()
{
return this.Tag == OptionType.None;
}
public bool MatchSome(out T value)
{
if (this.Tag == OptionType.Some)
{
value = ((Some<T>)this).Value;
}
else
{
value = default(T);
}
return this.Tag == OptionType.Some;
}
}
internal sealed class None<T> : Option<T>
{
public None() : base(OptionType.None) { }
}
internal sealed class Some<T> : Option<T>
{
private readonly T value;
public Some(T value)
: base(OptionType.Some)
{
this.value = value;
}
public T Value
{
get
{
return this.value;
}
}
}
internal static class Option
{
public static Option<T> None<T>()
{
return new None<T>();
}
public static Some<T> Some<T>(T value)
{
return new Some<T>(value);
}
}
internal static class OptionExtensions
{
public static Option<T2> Bind<T1, T2>(this Option<T1> option, Func<T1, Option<T2>> func)
{
T1 value1;
if (option.MatchSome(out value1))
{
return func(value1);
}
return Option.None<T2>();
}
public static Option<T2> Map<T1, T2>(this Option<T1> option, Func<T1, T2> func)
{
T1 value1;
if (option.MatchSome(out value1))
{
return Option.Some(func(value1));
}
return Option.None<T2>();
}
}
现在我需要一个操作来提取值(如果不是None
或返回默认值)。
我想知道这是否可以使用 and 的组合Map
,Bind
但我认为不是。
所以我回到F# 文档,它给了我一些其他有用的扩展方法的提示,但不完全是我需要的。
我设计了这个功能来满足我的需要:
public static T2 Return<T1, T2>(this Option<T1> option, Func<T1, T2> func, T2 noneValue)
{
T1 value1;
if (option.MatchSome(out value1))
{
return func(value1);
}
return noneValue;
}
因此,为了不重新发明轮子,问题是:是否有参考或通用功能模式来定义Option<T>
monad 上的操作?根据需要添加新操作是否正确?