2010年5月22日土曜日

HaskellのMaybeクラスをC#で作ってみた。

Maybeクラスを作ってみました。
Nothingの場合にnullにしていたんですけど、コンパイルエラーに!
default(T)なんてのがあるんですね。

しかし、default(T)は必要あるのか?
Nothingの場合は値を持つ必要が無いので、Valueで例外、HasValueでfalseを返すだけのクラスがあっても良さそう。


HaskellのMaybeクラスをC#で作ってみた。その2

default(T)を消してクラスを分離したバージョンを作成しました。



public class Maybe<T>
{
private readonly T _value;
private readonly bool _hasValue;
public Maybe(T value)
: this(value, true)
{
if (ReferenceEquals(value, null))
{
throw new ArgumentNullException("value is null");
}
}
private Maybe(T value, bool hasValue)
{
_value = value;
_hasValue = hasValue;
}
public bool HasValue
{
get { return _hasValue; }
}

public T Value
{
get
{
if (_hasValue)
{
return _value;
}
throw new InvalidOperationException("No Value");
}
}

public T GetValue(T defaultValue)
{
if (_hasValue)
{
return _value;
}
return defaultValue;
}

public static bool operator ==(Maybe<T> left, Maybe<T> right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (ReferenceEquals(left, null))
{
return false;
}
return left.Equals(right);
}
public static bool operator !=(Maybe<T> left, Maybe<T> right)
{
return !(left == right);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
{
return true;
}

Maybe<T> maybe = obj as Maybe<T>;
if (ReferenceEquals(maybe, null))
{
return false;
}
if (_hasValue != maybe.HasValue)
{
return false;
}
if (_hasValue)
{
return _value.Equals(maybe.Value);
}
return true;
}
public override int GetHashCode()
{
if (_hasValue)
{
return _value.GetHashCode() * 751;
}
return 0;
}
public static explicit operator T(Maybe<T> maybe)
{
return maybe.Value;
}
public static Maybe<T> Nothing = new Maybe<T>(default(T), false);

public static Maybe<T> Just(T value)
{
return new Maybe<T>(value);
}
}



NUnitのテストコード
も公開しています。
.

0 件のコメント:

ラベル