예제 #1
0
 /// <summary>
 /// Divide to future values that are integers. Return a double (as we should be!!).
 /// </summary>
 /// <param name="numerator"></param>
 /// <param name="denominator"></param>
 /// <returns></returns>
 public static IFutureValue <double> DivideBy(this IFutureValue <int> numerator, IFutureValue <int> denominator)
 {
     return(new DoFutureOperator <double>(
                () => ((double)numerator.Value) / ((double)denominator.Value),
                () => numerator.HasValue && denominator.HasValue,
                () => Task.WhenAll(numerator.GetAvailibleTask(), denominator.GetAvailibleTask())));
 }
예제 #2
0
 /// <summary>
 /// When requested, we will extract the value from the source.
 /// </summary>
 /// <typeparam name="TSource"></typeparam>
 /// <typeparam name="TResult"></typeparam>
 /// <param name="source"></param>
 /// <param name="extractor"></param>
 /// <returns></returns>
 public static IFutureValue <TResult> ExtractValue <TSource, TResult>(this IFutureValue <TSource> source, Func <TSource, TResult> extractor)
 {
     return(new DoFutureOperator <TResult>(
                () => extractor(source.Value),
                () => source.HasValue,
                () => source.GetAvailibleTask()
                ));
 }
예제 #3
0
 /// <summary>
 /// Select pattern - so that one can access the monad in situ.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <typeparam name="M"></typeparam>
 /// <param name="self"></param>
 /// <param name="map"></param>
 /// <returns></returns>
 public static IFutureValue <T> Select <T, M>(this IFutureValue <M> self, Func <M, T> map)
 {
     return(new DoFutureOperator <T>(
                () => map(self.Value),
                () => self.HasValue,
                () => self.GetAvailibleTask()
                ));
 }
예제 #4
0
 /// <summary>
 /// Return a FV that contains the cast held object.
 /// </summary>
 /// <typeparam name="TResult">The type for the result of the cast</typeparam>
 /// <returns>A FV that holds onto the cast version of the original value</returns>
 public IFutureValue <TResult> To <TResult>()
     where TResult : class
 {
     return(new DoFutureOperator <TResult>(
                () => _value.Value as TResult,
                () => _value.HasValue,
                () => _value.GetAvailibleTask()
                ));
 }
예제 #5
0
 /// <summary>
 /// Returns a future value that uses two different future values to calculate a third. A Func does the
 /// actual manipulation.
 /// </summary>
 /// <typeparam name="TSource1"></typeparam>
 /// <typeparam name="TSource2"></typeparam>
 /// <typeparam name="TResult"></typeparam>
 /// <param name="source1"></param>
 /// <param name="source2"></param>
 /// <param name="extractor"></param>
 /// <returns></returns>
 public static IFutureValue <TResult> ExtractValue <TSource1, TSource2, TResult>(this IFutureValue <TSource1> source1,
                                                                                 IFutureValue <TSource2> source2,
                                                                                 Func <TSource1, TSource2, TResult> extractor)
 {
     return(new DoFutureOperator <TResult>(
                () => extractor(source1.Value, source2.Value),
                () => source2.HasValue && source1.HasValue,
                () => Task.WhenAll(source1.GetAvailibleTask(), source2.GetAvailibleTask())
                ));
 }
예제 #6
0
        /// <summary>
        /// Implement the select many pattern to allow monadic calculations
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <param name="self"></param>
        /// <param name="select"></param>
        /// <param name="project"></param>
        /// <returns>A future value that applies the projection operator</returns>
        /// <remarks>
        /// The projection is straight forward SelectMany (not that it is straight forward in any way).
        /// Doing the HasValue guy, however, is not, as we want to be a little careful not to call Value
        /// on anything that doesn't have a value yet. So we are relying on the fact that self.Value won't
        /// get calculated until after the self.HasValue has been "ok"d.
        /// </remarks>
        public static IFutureValue <V> SelectMany <T, U, V>(
            this IFutureValue <T> self,
            Func <T, IFutureValue <U> > select,
            Func <T, U, V> project)
        {
            var fvcache = new FutureValueCache <T>(self);

            return(new DoFutureOperator <V>(
                       () =>
            {
                var resT = fvcache.GetValue();
                var resUOpt = select(resT);
                var resU = resUOpt.Value;
                var resV = project(resT, resU);
                return resV;
            },
                       () => self.HasValue && select(fvcache.GetValue()).HasValue,
                       () => Task.WhenAll(self.GetAvailibleTask(), select(fvcache.GetValue()).GetAvailibleTask())
                       ));
        }
예제 #7
0
 public void OnCompleted(Action continuation)
 {
     _ifv.GetAvailibleTask().ContinueWith(t => continuation());
 }