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