You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
9.2 KiB
326 lines
9.2 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Tools.Maybes
|
|
{
|
|
static class test
|
|
{
|
|
public static void maybe()
|
|
{
|
|
var result = Maybe.Some(false);
|
|
|
|
if(result)
|
|
{
|
|
bool value = result;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
|
|
result.Match(Some: value =>
|
|
{
|
|
return 10;
|
|
}, None: () =>
|
|
{
|
|
return 0;
|
|
});
|
|
|
|
var valresult = ValueMaybe.Some(10.1f);
|
|
if(valresult)
|
|
{
|
|
float res = valresult;
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
|
|
valresult.Match(Some: value =>
|
|
{
|
|
return value * 2;
|
|
}, None: () =>
|
|
{
|
|
return 0;
|
|
});
|
|
}
|
|
/* public void tresult()
|
|
{
|
|
var result = Result.Ok("hi");
|
|
}*/
|
|
}
|
|
|
|
public static class ValueMaybe
|
|
{
|
|
public static ValueMaybe<T> Some<T>(T value)
|
|
=> new ValueMaybe<T>(value, true);
|
|
public static ValueMaybe<T> None<T>()
|
|
=> new ValueMaybe<T>(default, false);
|
|
}
|
|
public readonly struct ValueMaybe<T>
|
|
{
|
|
private readonly T value;
|
|
private readonly bool hasValue;
|
|
|
|
public bool Equals(ValueMaybe<T> other)
|
|
{
|
|
return other.hasValue == this.hasValue && (ReferenceEquals(value, other.value) || (value?.Equals(other.value) ?? false));
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
return hasValue ? Math.Abs(value?.GetHashCode() ?? 0) : -1;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return (obj is ValueMaybe<T> some && Equals(some)) || (hasValue && obj is T val && (ReferenceEquals(val, value) || (value?.Equals(val) ?? false)));
|
|
}
|
|
|
|
internal ValueMaybe(T value, bool hasValue)
|
|
{
|
|
this.hasValue = hasValue;
|
|
this.value = value;
|
|
}
|
|
|
|
public static bool operator true(ValueMaybe<T> some)
|
|
=> some.hasValue;
|
|
public static bool operator false(ValueMaybe<T> some)
|
|
=> !some.hasValue;
|
|
|
|
public static implicit operator T(ValueMaybe<T> input)
|
|
=> input.hasValue ? input.value : throw new InvalidCastException("No value");
|
|
public static implicit operator ValueMaybe<T>(T input)
|
|
=> ValueMaybe.Some(input);
|
|
|
|
public T Value => value;
|
|
public bool HasValue => hasValue;
|
|
|
|
public bool TryGetValue(out T value)
|
|
{
|
|
if(HasValue)
|
|
{
|
|
value = Value;
|
|
return true;
|
|
}
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
public void Match(Action<T> Some=null, Action None=null)
|
|
{
|
|
if (hasValue)
|
|
Some?.Invoke(value);
|
|
else
|
|
None?.Invoke();
|
|
}
|
|
public V Match<V>(Func<T, V> Some=null, Func<V> None=null)
|
|
{
|
|
if(hasValue)
|
|
{
|
|
if (Some != null) return Some(value);
|
|
else return default;
|
|
}
|
|
else
|
|
{
|
|
if (None != null) return None();
|
|
else return default;
|
|
}
|
|
}
|
|
|
|
public static bool operator ==(ValueMaybe<T> left, ValueMaybe<T> right)
|
|
{
|
|
return left.Equals(right);
|
|
}
|
|
|
|
public static bool operator !=(ValueMaybe<T> left, ValueMaybe<T> right)
|
|
{
|
|
return !(left == right);
|
|
}
|
|
}
|
|
|
|
public sealed class Some<T> : Maybe<T>
|
|
{
|
|
public override T Value { get; }
|
|
internal Some(T value)
|
|
{
|
|
Value = value;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is Some<T> some && (ReferenceEquals(some.Value, Value) || (some.Value?.Equals(Value) ?? false));
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
return Math.Abs(Value?.GetHashCode() ?? 0);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return "Some(" + (Value?.ToString() ?? "null") + ")";
|
|
}
|
|
}
|
|
public sealed class None<T> : Maybe<T>
|
|
{
|
|
internal None() { }
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is None<T>;
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return "None";
|
|
}
|
|
}
|
|
public static class Maybe
|
|
{
|
|
public static Maybe<T> Some<T>(T value)
|
|
=> new Some<T>(value);
|
|
|
|
public static Maybe<T> None<T>()
|
|
=> new None<T>();
|
|
}
|
|
public abstract class Maybe<T>
|
|
{
|
|
public static bool operator true(Maybe<T> input)
|
|
=> input is Some<T>;
|
|
public static bool operator false(Maybe<T> input)
|
|
=> input is None<T>;
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
public override string ToString()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public static bool operator ==(Maybe<T> left, T right)
|
|
=> left.HasValue && (left == Maybe.Some(right));
|
|
public static bool operator !=(Maybe<T> left, T right)
|
|
=> !(left == right);
|
|
public static bool operator ==(Maybe<T> left, Maybe<T> right)
|
|
{
|
|
return ReferenceEquals(left, right) || (left?.Equals(right) ?? false);
|
|
}
|
|
public static bool operator !=(Maybe<T> left, Maybe<T> right)
|
|
=> !(left == right);
|
|
|
|
public static implicit operator T(Maybe<T> some) => some is Some<T> thing ? thing : throw new InvalidCastException("No value");
|
|
public static implicit operator Maybe<T>(T some) => new Some<T>(some);
|
|
|
|
public virtual T Value => (T)this;
|
|
public bool HasValue => this is Some<T>;
|
|
|
|
public bool TryGetValue(out T value)
|
|
{
|
|
if(this is Some<T> thing)
|
|
{
|
|
value = thing.Value;
|
|
return true;
|
|
}
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
public void Match(Action<T> Some = null, Action None = null)
|
|
{
|
|
if (this is Some<T> some)
|
|
{
|
|
Some?.Invoke(some.Value);
|
|
}
|
|
else if (this is None<T> none)
|
|
None?.Invoke();
|
|
throw new InvalidOperationException("Maybe is neither some nor none.");
|
|
}
|
|
public V Match<V>(Func<T, V> Some = null, Func<V> None = null)
|
|
{
|
|
if (this is Some<T> some)
|
|
{
|
|
if (Some == null) return default;
|
|
else return Some(some.Value);
|
|
}
|
|
else if (this is None<T> none)
|
|
{
|
|
if (None == null) return default;
|
|
else
|
|
return None();
|
|
}
|
|
throw new InvalidOperationException("Maybe is neither some nor none.");
|
|
}
|
|
}
|
|
#if REWORK && false
|
|
public class Ok<T,E> : Result<T,E>
|
|
{
|
|
public override T Value { get; }
|
|
public Ok(T value)
|
|
{
|
|
Value = value;
|
|
}
|
|
}
|
|
public class Err<T,E> : Result<T,E>
|
|
{
|
|
public override E Error { get; }
|
|
public Err(E exception)
|
|
{
|
|
Error = exception;
|
|
}
|
|
}
|
|
public static class Result
|
|
{
|
|
public static Ok<T, E> Ok<T, E>(T value)
|
|
=> new Ok<T, E>(value);
|
|
public static Err<T, E> Err<T, E>(E value)
|
|
=> new Err<T, E>(value);
|
|
}
|
|
public abstract class Result<T,E>
|
|
{
|
|
public static bool operator true(Result<T, E> input)
|
|
=> input is Ok<T, E>;
|
|
public static bool operator false(Result<T, E> input)
|
|
=> input is Err<T, E>;
|
|
|
|
public virtual T Value => (T)this;
|
|
public virtual E Error => (E)this;
|
|
|
|
|
|
public bool TryGetValue(out T value)
|
|
{
|
|
if (this is Ok<T, E> thing)
|
|
{
|
|
value = thing.Value;
|
|
return true;
|
|
}
|
|
value = default;
|
|
return false;
|
|
}
|
|
public bool TryGetError(out E value)
|
|
{
|
|
if (this is Err<T, E> thing)
|
|
{
|
|
value = thing.Error;
|
|
return true;
|
|
}
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
public static implicit operator T(Result<T, E> validResult) => validResult is Ok<T, E> ok ? ok.Value : throw new InvalidCastException("No value");
|
|
public static implicit operator E(Result<T, E> invalidResult) => invalidResult is Err<T, E> ok ? ok.Error : throw new InvalidCastException("No exception");
|
|
}
|
|
#endif
|
|
}
|