canto/Assets/Scripts/System/Option.cs

136 lines
4.3 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
namespace KitsuneCafe.Sys
{
public class Option
{
public static IOption<T> Some<T>(T value) => new Some<T>(value);
public static IOption<T> None<T>() => new None<T>();
}
public interface IOption<T> : IEnumerable<T>
{
IOption<U> And<U>(IOption<U> optb);
IOption<U> AndThen<U>(Func<T, IOption<U>> fn);
IOption<T> Filter(Predicate<T> predicate);
bool IsSome();
bool IsNone();
IOption<U> Map<U>(Func<T, U> transform);
U MapOr<U>(U defaultValue, Func<T, U> transform);
U MapOrDefault<U>(Func<T, U> transform);
U MapOrElse<U>(Func<U> defaultFn, Func<T, U> transform);
IResult<T, E> OkOr<E>(E err);
IResult<T, E> OkOrElse<E>(Func<E> err);
IOption<T> Or(IOption<T> optb);
IOption<T> OrElse(Func<IOption<T>> optb);
IOption<T> Xor(IOption<T> optb);
T Unwrap();
T UnwrapOr(T defaultValue);
T UnwrapOrDefault();
T UnwrapOrElse(Func<T> defaultValue);
}
public static class Option<T>
{
public static Some<T> Some(T value) => new(value);
public static readonly None<T> None = new();
}
public readonly struct Some<T> : IOption<T>
{
private readonly T value;
public Some(T value)
{
this.value = value;
}
public IOption<U> And<U>(IOption<U> optb) => optb;
public IOption<U> AndThen<U>(Func<T, IOption<U>> fn) => fn(value);
public IOption<T> Filter(Predicate<T> predicate)
{
return predicate(value) ? this : Option<T>.None;
}
public bool IsSome() => true;
public bool IsNone() => false;
public IOption<U> Map<U>(Func<T, U> transform) => new Some<U>(transform(value));
public U MapOr<U>(U defaultValue, Func<T, U> transform) => transform(value);
public U MapOrDefault<U>(Func<T, U> transform) => transform(value);
public U MapOrElse<U>(Func<U> defaultFn, Func<T, U> transform) => transform(value);
public IResult<T, E> OkOr<E>(E err) => new Ok<T, E>(value);
public IResult<T, E> OkOrElse<E>(Func<E> err) => new Ok<T, E>(value);
public IOption<T> Or(IOption<T> optb) => this;
public IOption<T> OrElse(Func<IOption<T>> optb) => this;
public IOption<T> Xor(IOption<T> optb)
{
return optb.IsNone() ? this : Option<T>.None;
}
public T Unwrap() => value;
public T UnwrapOr(T defaultValue) => value;
public T UnwrapOrDefault() => value;
public T UnwrapOrElse(Func<T> defaultValue) => value;
public IEnumerator<T> GetEnumerator()
{
yield return value;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public readonly struct None<T> : IOption<T>
{
public IOption<U> And<U>(IOption<U> optb) => Option<U>.None;
public IOption<U> AndThen<U>(Func<T, IOption<U>> fn) => Option<U>.None;
public IOption<T> Filter(Predicate<T> predicate) => this;
public bool IsSome() => false;
public bool IsNone() => true;
public IOption<U> Map<U>(Func<T, U> transform) => Option<U>.None;
public U MapOr<U>(U defaultValue, Func<T, U> transform) => defaultValue;
public U MapOrDefault<U>(Func<T, U> transform) => default;
public U MapOrElse<U>(Func<U> defaultFn, Func<T, U> transform) => defaultFn();
public IResult<T, E> OkOr<E>(E err) => new Err<T, E>(err);
public IResult<T, E> OkOrElse<E>(Func<E> err) => new Err<T, E>(err());
public IOption<T> Or(IOption<T> optb) => optb;
public IOption<T> OrElse(Func<IOption<T>> optb) => optb();
public IOption<T> Xor(IOption<T> optb)
{
return optb.IsNone() ? this : Option<T>.None;
}
public T Unwrap()
{
throw new NullReferenceException();
}
public T UnwrapOr(T defaultValue) => defaultValue;
public T UnwrapOrDefault() => default;
public T UnwrapOrElse(Func<T> defaultValue) => defaultValue();
public IEnumerator<T> GetEnumerator()
{
yield break;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}