예제 #1
0
            // Second law: Select preserves the composition operator.
            //   fmap (f . g)  ==  fmap f . fmap g
            public static bool CompositionRule <T1, T2, T3>(
                Mayhap <T1> mayhap, Func <T2, T3> f, Func <T1, T2> g)
            {
#if STRICT_HASKELL
                return(Map(x => f(g(x)), mayhap)
                       == Map(f, Map(g, mayhap)));
#else
                return(mayhap.Select(x => f(g(x)))
                       == mayhap.Select(g).Select(f));
#endif
            }
예제 #2
0
        /// <summary>
        /// (&lt;$)
        /// <para>a = TResult, b = TSource</para>
        /// <para>Create a new f a from an f b by replacing all of the values in
        /// the f b by a given value of type a.</para>
        /// </summary>
        public static Mayhap <TResult> ReplaceWith <TSource, TResult>(
            TResult value,
            Mayhap <TSource> mayhap)
            where TResult : notnull
        {
            // (<$) :: Functor f => a -> f b -> f a | infixl 4 |
            //
            // (<$) :: a -> f b -> f a
            // (<$) =  fmap . const
            //
            // Replace all locations in the input with the same value. The
            // default definition is fmap . const, but this may be overridden
            // with a more efficient version.
            //
            // Examples:
            //   "xxx" <$ Nothing == Nothing
            //   "xxx" <$ Just 1  == Just "xxx"

#if STRICT_HASKELL
            return(Map(__const, mayhap));

            // NB: this is just (_ => value).
            TResult __const(TSource x) => Thunks <TResult, TSource> .Const1(value, x);
#else
            return(mayhap.Select(_ => value));
#endif
        }
예제 #3
0
        public static Mayhap <TResult> Join <T, TInner, TKey, TResult>(
            this Mayhap <T> @this,
            Mayhap <TInner> inner,
            Func <T, TKey> outerKeySelector,
            Func <TInner, TKey> innerKeySelector,
            Func <T, TInner, TResult> resultSelector)
        {
            Utilities.Guard.NotNull(outerKeySelector, nameof(outerKeySelector));
            Utilities.Guard.NotNull(innerKeySelector, nameof(innerKeySelector));
            Utilities.Guard.NotNull(resultSelector, nameof(resultSelector));

            var comparer = EqualityComparer <TKey> .Default;

            var keyLookup = __getKeyLookup();

            return(@this.SelectMany(__valueSelector, resultSelector));

            Mayhap <TInner> __valueSelector(T outer) => keyLookup(outerKeySelector(outer));

            Func <TKey, Mayhap <TInner> > __getKeyLookup()
            {
                return(outerKey =>
                       inner.Select(innerKeySelector)
                       .Where(innerKey => comparer.Equals(innerKey, outerKey))
                       .ContinueWith(inner));
            }
        }
예제 #4
0
            // First law: the identity map is a fixed point for Select.
            //   fmap id  ==  id
            public static bool IdentityRule <T>(Mayhap <T> mayhap)
            {
#if STRICT_HASKELL
                return(Map(Thunks <T> .Ident, mayhap)
                       == Thunks <Mayhap <T> > .Ident(mayhap));
#else
                return(mayhap.Select(Thunks <T> .Ident)
                       == Thunks <Mayhap <T> > .Ident(mayhap));
#endif
            }
예제 #5
0
        public static Mayhap <Mayhap <T> > Optional <T>(this Mayhap <T> @this)
        {
            // optional :: Alternative f => f a -> f (Maybe a)
            // optional v = Just <$> v <|> pure Nothing
            //
            // One or none.

#if STRICT_HASKELL
            return(Map(Mayhap <T> .Some, @this).Otherwise(Pure(Mayhap <T> .None)));
#else
            return(@this.Select(Mayhap <T> .Some).OrElse(Pure(Mayhap <T> .None)));
#endif
        }
예제 #6
0
        /// <summary>
        /// void
        /// <para>a = TSource, () = Unit</para>
        /// <para>Create a new f () from an f a by replacing all of the values
        /// in the f a by ().</para>
        /// </summary>
        public static Mayhap <Unit> Skip <TSource>(
            this Mayhap <TSource> @this)
        {
            // void :: Functor f => f a -> f ()
            // void x = () <$ x
            //
            // void value discards or ignores the result of evaluation, such as
            // the return value of an IO action.

#if STRICT_HASKELL
            return(ReplaceWith(Abc.Unit.Default, @this));
#else
            return(@this.Select(_ => Abc.Unit.Default));
#endif
        }
예제 #7
0
        /// <summary>
        /// (&lt;**&gt;)
        /// <para>A variant of (&lt;*&gt;) with the arguments reversed.</para>
        /// </summary>
        public static Mayhap <TResult> Apply <TSource, TResult>(
            this Mayhap <TSource> @this,
            Mayhap <Func <TSource, TResult> > applicative)
        {
            // (<**>) :: Applicative f => f a -> f (a -> b) -> f b
            // (<**>) = liftA2(\a f -> f a)
            //
            // A variant of '<*>' with the arguments reversed.

#if STRICT_HASKELL
            return(Invoke(applicative, @this));
#else
            return(applicative.Bind(f => @this.Select(f)));
#endif
        }
예제 #8
0
        /// <summary>
        /// fmap
        /// <para>a = TSource, b = TResult</para>
        /// <para>Create a new f b from an f a using the results of calling a
        /// function on every value in the f a.</para>
        /// </summary>
        public static Mayhap <TResult> Map <TSource, TResult>(
            Func <TSource, TResult> mapper,
            Mayhap <TSource> mayhap)
        {
            // fmap :: (a -> b) -> f a -> f b
            //
            // Examples:
            //   fmap (+1) (Just 1)  ==  Just 2
            //   fmap (+1) Nothing   ==  Nothing

#if STRICT_HASKELL
            throw new NotImplementedException("Functor fmap");
#else
            return(mayhap.Select(mapper));
#endif
        }
예제 #9
0
        /// <summary>(&lt;&amp;&gt;)</summary>
        public static Mayhap <TResult> Map <TSource, TResult>(
            this Mayhap <TSource> @this,
            Func <TSource, TResult> mapper)
        {
            // [Functor]
            //   (<&>) :: Functor f => f a -> (a -> b) -> f b | infixl 1 |
            //   (<&>) = flip fmap
            //
            //    Flipped version of <$>.
            //
            // Examples:
            //   Just 1  <&> (+1)  ==  Just 2
            //   Nothing <&> (+1)  ==  Nothing

#if STRICT_HASKELL
            return(Map(mapper, @this));
#else
            return(@this.Select(mapper));
#endif
        }
예제 #10
0
        /// <summary>
        /// ($&gt;)
        /// <para>a = TSource, b = TResult</para>
        /// <para>Create a new f b, from an f a by replacing all of the values
        /// in the f a by a given value of type b.</para>
        /// </summary>
        public static Mayhap <TResult> ReplaceWith <TSource, TResult>(
            this Mayhap <TSource> @this,
            TResult value)
            where TResult : notnull
        {
            // ($>) :: Functor f => f a -> b -> f b | infixl 4 |
            // ($>) = flip (<$)
            //
            // Flipped version of <$.
            //
            // Examples:
            //   Nothing $> "xxx" == Nothing
            //   Just 1 $> "xxx"  == Just "xxx"

#if STRICT_HASKELL
            return(ReplaceWith(value, @this));
#else
            return(@this.Select(_ => value));
#endif
        }