canto/Assets/Scripts/System/Option.cs
2025-08-14 19:11:32 -04:00

128 lines
3.2 KiB
C#

using System;
namespace KitsuneCafe.Sys
{
public class Option
{
public static IOption<T> Some<T>(T value) => IOption<T>.Some(value);
public static IOption<T> None<T>() => IOption<T>.None();
}
public interface IOption<T>
{
private static IOption<T> none = new None<T>();
public abstract bool IsSome { get; }
public static IOption<T> Some(T value) => new Some<T>(value);
public static IOption<T> None() => none;
public abstract T Unwrap();
public abstract IOption<TResult> SelectMany<TResult>(Func<T, IOption<TResult>> func);
public abstract IOption<TResult> Select<TResult>(Func<T, TResult> func);
public abstract IOption<T> Where(Func<T, bool> predicate);
public abstract TResult Match<TResult>(Func<T, TResult> ifSome, Func<TResult> ifNone);
public abstract T UnwrapOrDefault(T defaultValue = default);
public abstract T UnwrapOrElse(Func<T> func);
public virtual IOption<T> Do(Action<T> func)
{
if (IsSome) { func(Unwrap()); }
return this;
}
}
public readonly struct Some<T> : IOption<T>
{
private readonly T value;
public readonly bool IsSome => true;
internal Some(T value)
{
this.value = value;
}
public IOption<TResult> SelectMany<TResult>(Func<T, IOption<TResult>> func)
{
return func(value);
}
public T Unwrap()
{
return value;
}
public IOption<TResult> Select<TResult>(Func<T, TResult> func)
{
return IOption<TResult>.Some(func(value));
}
public IOption<T> Where(Func<T, bool> predicate)
{
if (predicate(value))
{
return this;
}
return IOption<T>.None();
}
public TResult Match<TResult>(Func<T, TResult> ifSome, Func<TResult> ifNone)
{
return ifSome(value);
}
public T UnwrapOrDefault(T defaultValue = default)
{
return value;
}
public T UnwrapOrElse(Func<T> _func)
{
return value;
}
}
public readonly struct None<T> : IOption<T>
{
public readonly bool IsSome => false;
public IOption<TResult> SelectMany<TResult>(Func<T, IOption<TResult>> func)
{
return IOption<TResult>.None();
}
public T Unwrap()
{
throw new InvalidOperationException("Attempted to unwrap value of None.");
}
public IOption<TResult> Select<TResult>(Func<T, TResult> func)
{
return IOption<TResult>.None();
}
public IOption<T> Where(Func<T, bool> predicate)
{
return IOption<T>.None();
}
public TResult Match<TResult>(Func<T, TResult> ifSome, Func<TResult> ifNone)
{
return ifNone();
}
public T UnwrapOrDefault(T defaultValue = default)
{
return defaultValue;
}
public T UnwrapOrElse(Func<T> func)
{
return func();
}
}
}