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

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
}