// using System.Diagnostics;
// using System.Diagnostics.CodeAnalysis;
// using System.Runtime.CompilerServices;
// using SJK.Functional;
// namespace SJK.Functional
// {
// ///
// /// A simple implementation of a monadic option, which can hold either a value of type T or no value.
// ///
// public struct Option : IEquatable>
// {
// private readonly T? _value;
// [MemberNotNullWhen(true, nameof(_value))]
// public bool HasValue { get; }
// public static Option None => new(default, false);
// public static Option Some(T value) => new(value, true);
// ///
// /// A constructor for creating an instance of the Option struct.
// ///
// private Option(T? value, bool hasValue)
// {
// Debug.Assert(!(value is null && hasValue), "Can not create an option with a null value had say it has one");
// _value = value;
// HasValue = hasValue;
// }
// ///
// /// Gets the held value if it exists. Throws an exception if there's no value.
// ///
// public T? Value => HasValue ? _value : throw new InvalidOperationException("Can not retrieve value when there is no value.");
// ///
// /// Applies a function to the held value if it exists, otherwise applies another function.
// ///
// /// The type of result produced by the functions.
// public TResult Match(Func some, Func none)
// {
// // If we have a value, apply 'some' to it. Otherwise, apply 'none'.
// return HasValue ? some(_value) : none();
// }
// ///
// /// Maps the held value if it exists using the given function, otherwise returns an empty option.
// ///
// /// The type of result produced by the mapping function.
// public Option Map(Func f)
// {
// // If we have a value, map it and wrap the result in another option. Otherwise, return an empty option.
// return HasValue ? Option.Some(f(_value)) : Option.None;
// }
// ///
// /// Binds the held value if it exists using the given function, otherwise returns an empty option.
// ///
// /// The type of result produced by the binding function.
// public Option Bind(Func> f)
// {
// // If we have a value, bind it and wrap the result in another option. Otherwise, return an empty option.
// return HasValue ? f(_value) : Option.None;
// }
// ///
// /// Returns the held value if it exists, otherwise returns a default value.
// ///
// public T OrDefault(T value)
// {
// // If we have a value, return it. Otherwise, return the default value.
// return HasValue ? _value : value;
// }
// ///
// /// Returns the held value if it exists, otherwise returns a result from a factory function.
// ///
// public T Or(Func factory)
// {
// // If we have a value, return it. Otherwise, invoke the factory function and return its result.
// return HasValue ? _value : factory();
// }
// public override bool Equals([NotNullWhen(true)] object? obj) => obj is Option other && Equals(other);
// ///
// /// Checks for equality with another option of type T.
// ///
// public bool Equals(Option other)
// {
// // If both options have values, check their equality. Otherwise, consider them equal if they're both empty.
// return (HasValue == other.HasValue) && (!HasValue || EqualityComparer.Default.Equals(_value, other._value));
// }
// public override int GetHashCode() => HasValue ? EqualityComparer.Default.GetHashCode(_value) : 0;
// ///
// /// Returns a string representation of this option.
// ///
// public override string ToString()
// {
// // If we have a value, return it as a 'Some' with the value. Otherwise, return an empty 'None'.
// return HasValue ? $"Some({_value})" : $"None<{typeof(T).Name}>()";
// }
// }
// }