/// <summary>
        /// If the given value is of a numeric type, converts the value to a string representation
        /// using the specified format and culture-specific format information. Returns empty if this value is not of a
        /// numeric type.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="format"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static Opt <string> NumericValueToStringOpt(this IConvertible value, string format, IFormatProvider provider)
        {
            switch (Classify(value))
            {
            case SimpleTypeClassification.Decimal:
            {
                return(Opt.Full(((decimal)value).ToString(format, provider)));
            }

            case SimpleTypeClassification.FloatingPoint:
            {
                return(value.FloatingPointValueOpt()
                       .Select(v => v.ToString(format, provider))
                       .SingleFixOpt());
            }

            case SimpleTypeClassification.SignedIntegral:
            {
                return(value.SignedIntegralValueOpt()
                       .Select(v => v.ToString(format, provider))
                       .SingleFixOpt());
            }

            case SimpleTypeClassification.UnsignedIntegral:
            {
                return(value.UnsignedIntegralValueOpt()
                       .Select(v => v.ToString(format, provider))
                       .SingleFixOpt());
            }

            default:
                return(Opt.Empty <string>());
            }
        }
        /// <summary>
        /// If the specified value is of any numeric type, retrieves the value as a <c>decimal</c>,
        /// casting if necessary.
        /// <para>The result is empty if the specified value is not of a numeric type.</para>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Opt <decimal> NumericValueAsDecimalOpt(this IConvertible value)
        {
            switch (Classify(value))
            {
            case SimpleTypeClassification.Decimal:
            {
                return(value.DecimalValueOpt());
            }

            case SimpleTypeClassification.FloatingPoint:
            {
                return(value
                       .FloatingPointValueOpt()
                       .SelectFix(doubleValue => (decimal)doubleValue));
            }

            case SimpleTypeClassification.SignedIntegral:
            {
                return(value
                       .SignedIntegralValueOpt()
                       .SelectFix(longValue => (decimal)longValue));
            }

            case SimpleTypeClassification.UnsignedIntegral:
            {
                return(value
                       .UnsignedIntegralValueOpt()
                       .SelectFix(ulongValue => (decimal)ulongValue));
            }

            default:
                return(Opt.Empty <decimal>());
            }
        }