/// <summary>
        /// Map both the input and output of a decoder to
        /// produce a new decoder.
        /// </summary>
        public static Decoder <TRaw2, T2> Dimap <TRaw1, T1, TRaw2, T2>(
            this Decoder <TRaw1, T1> decoder,
            [NotNull] Func <TRaw2, TRaw1> f,
            [NotNull] Func <T1, T2> g)
        {
            if (f == null)
            {
                throw new ArgumentNullException(nameof(f));
            }
            if (g == null)
            {
                throw new ArgumentNullException(nameof(g));
            }

            return(new Decoder <TRaw2, T2>((id, x) => decoder.Run(id, f(x)).Map(g), decoder.Id));
        }
        /// <summary>
        /// Return a new Decoder computed from the result of the first.
        /// </summary>
        public static Decoder <TRaw, T2> Bind <TRaw, T1, T2>(
            this Decoder <TRaw, T1> decoder,
            [NotNull] Func <T1, Decoder <TRaw, T2> > f)
        {
            if (f == null)
            {
                throw new ArgumentNullException(nameof(f));
            }

            return(new Decoder <TRaw, T2>(
                       (id, x) =>
                       from result1 in decoder.Run(id, x)
                       from result2 in f(result1).Run(id, x)
                       select result2,
                       decoder.Id));
        }
 /// <summary>
 /// Create a Decoder that will select the first succesful result, or
 /// the last failure.
 /// </summary>
 public static Decoder <TRaw, T> Or <TRaw, T>(
     this Decoder <TRaw, T> decoder1,
     Decoder <TRaw, T> decoder2)
 {
     return(new Decoder <TRaw, T>((id, x) => decoder1.Run(id, x) || decoder2.Run(id, x)));
 }