/// <summary>
        /// If the specified value is of any integral type and can be cast losslessly to a
        /// <c>ulong</c>, gets the value as a <c>ulong</c>.
        /// <para>
        /// If the value is of a signed integral type but can be converted to a <c>ulong</c> without
        /// losing data (i.e., the value is nonnegative), this method gets the converted value.
        /// </para>
        /// <para>
        /// The result is empty if the specified value is not of an integral type or has a negative value.
        /// </para>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Opt <ulong> UnsignedIntegralValueOpt(this IConvertible value)
        {
            if (value is ulong)
            {
                return(Opt.Full((ulong)value));
            }

            // Returns empty option if the value is negative.
            return(value.IntegralValueWidenedToLongOpt()
                   .WhereFix(lv => lv >= 0)
                   .SelectFix(lv => (ulong)lv));
        }
 /// <summary>
 /// If the specified value is of any integral type and can be cast losslessly to a
 /// <c>long</c>, gets the value as a <c>long</c>.
 /// <para>
 /// If the value is a <c>ulong</c> but can be converted to a <c>long</c> without losing
 /// data, this method gets the converted value.
 /// </para>
 /// <para>
 /// The result is empty if the specified value is not of an integral type or is of
 /// <c>ulong</c> with a value that cannot be stored losslessly as a <c>long</c>.
 /// </para>
 /// </summary>
 /// <param name="value"></param>
 /// <returns></returns>
 public static Opt <long> SignedIntegralValueOpt(this IConvertible value)
 {
     if (value is ulong)
     {
         long v = (long)value;
         if (v < 0)
         {
             return(Opt.Empty <long>());
         }
         return(Opt.Full(v));
     }
     else
     {
         return(value.IntegralValueWidenedToLongOpt());
     }
 }