/// <summary> /// Returns an <see cref="IAlternative{TSource}"/> containing <see cref="Maybe.Just{T}(T)"/> its value, if present, or <see cref="Maybe.Nothing{T}"/> otherwise. /// </summary> /// <typeparam name="TResult">The type of the value in <paramref name="alt"/>.</typeparam> /// <param name="alt">The <see cref="IAlternative{TSource}"/> to check.</param> public static IAlternative <Maybe <TResult> > Optional <TResult>(this IAlternative <TResult> alt) { var altM = (IAlternative <Maybe <TResult> >)alt.Map(x => Maybe.Just(x)); var nothingM = (IAlternative <Maybe <TResult> >)Applicative.PureUnsafe(Maybe.Nothing <TResult>(), altM.GetType()); return(altM.Alt(nothingM)); }
/// <summary> /// A limited form of traversal which traverses a <see cref="IFoldable{TSource}"/> structure and discards the results. /// </summary> /// <typeparam name="TSource">The type of the element in the input structure.</typeparam> /// <typeparam name="TResult">The type of the result of the action.</typeparam> /// <param name="applicative">The type of the applicative.</param> /// <param name="foldable">The object to fold.</param> /// <param name="f">The function to apply to each contained element.</param> public static IApplicative <Unit> TraverseDiscard <TSource, TResult>( this IFoldable <TSource> foldable, Type applicative, Func <TSource, IApplicative <TResult> > f) { return(foldable.Foldr( (x, acc) => f(x).ApRight(acc), Applicative.PureUnsafe(new Unit(), applicative))); }
/// <summary> /// An asynchronous monadic <see cref="CollectionExtensions.Unfold{TSeed, TResult}(TSeed, Func{TSeed, Maybe{ValueTuple{TSeed, TResult}}})"/> which generates a sequence each time the <paramref name="seed"/>-value evaluates to <see cref="Maybe.Just{T}(T)"/>.<br /> /// Equivalent to: /// <code> /// while ((await seed()).TryGetValue(_, y)) { yield return y; } /// </code> /// </summary> /// <typeparam name="TSource">The type of the seed/generated elements.</typeparam> /// <param name="seed">The monadic seed-value.</param> /// <param name="token">The cancellation token.</param> public static Task <IAsyncMonad <IEnumerable <TSource> > > UnfoldMAsync <TSource>( this Task <IAsyncMonad <Maybe <TSource> > > seed, CancellationToken token = default) { Task <IAsyncMonad <IEnumerable <TSource> > > go() { if (token.IsCancellationRequested) { return(Task.FromResult(Applicative.PureUnsafe((IEnumerable <TSource>)Array.Empty <TSource>(), seed.GetType()).ToAsyncMonad())); } var q = seed.BindAsync((Maybe <TSource> x) => x.TryGetValue(default, out var y)
/// <summary> /// Runs <paramref name="condition"/> repeatedly as long as it returns <c>true</c>, and runs <paramref name="body"/> each time, collecting the results.<br /> /// Equivalent to: /// <code> /// while (await condition()) /// { /// yield return await body(); /// } /// </code> /// </summary> /// <typeparam name="TSource">The type of the seed/generated elements.</typeparam> /// <param name="condition">The asynchronous monadic function which computes the condition.</param> /// <param name="body">The monadic body.</param> /// <param name="token">The cancellation token.</param> public static Task <IAsyncMonad <IEnumerable <TSource> > > WhileMAsync <TSource>( this Task <IAsyncMonad <bool> > condition, Func <Task <IAsyncMonad <TSource> > > body, CancellationToken token = default) { Type conditionType = null; Task <IAsyncMonad <IEnumerable <TSource> > > go() { if (token.IsCancellationRequested && conditionType is not null) { return(Task.FromResult( Applicative.PureUnsafe((IEnumerable <TSource>)Array.Empty <TSource>(), conditionType) .ToAsyncMonad())); } var q = condition.BindAsync((Type t, bool conditionResult) => { conditionType ??= t; return(conditionResult ? (body().BindAsync((TSource bodyResult) => go().MapAsync((IEnumerable <TSource> rest) => Task.FromResult(rest.Prepend(bodyResult)), token), token)) : Task.FromResult(Applicative.PureUnsafe((IEnumerable <TSource>)Array.Empty <TSource>(), t).ToAsyncMonad())); }, token); /*var q = * from conditionResult in condition * from results in conditionResult * ? from bodyResult in body() * from rest in go() * select rest.Prepend(bodyResult) * : Task.FromResult((IAsyncMonad<IEnumerable<TSource>>)Applicative.PureUnsafe((IEnumerable<TSource>)Array.Empty<TSource>(), condition.GetType())) * select results;*/ return(q); } return(go()); }