public static State <S, Reader <E, V> > SelectMany <S, E, T, U, V>( this State <S, T> self, Func <T, Reader <E, U> > bind, Func <T, U, V> project ) { if (bind == null) { throw new ArgumentNullException("bind"); } if (project == null) { throw new ArgumentNullException("project"); } return((S s) => { var resT = self(s); if (resT.IsBottom) { return StateResult.Bottom <S, Reader <E, V> >(s); } return StateResult.Return <S, Reader <E, V> >(resT.State, envInner => { var resU = bind(resT.Value)(envInner); if (resU.IsBottom) { return new ReaderResult <V>(default(V), true); } return ReaderResult.Return(project(resT.Value, resU.Value)); }); }); }
public static State <S, Writer <Out, V> > SelectMany <S, Out, T, U, V>( this State <S, T> self, Func <T, Writer <Out, U> > bind, Func <T, U, V> project ) { if (bind == null) { throw new ArgumentNullException("bind"); } if (project == null) { throw new ArgumentNullException("project"); } return((S s) => { var resT = self(s); if (resT.IsBottom) { return StateResult.Bottom <S, Writer <Out, V> >(s); } return StateResult.Return <S, Writer <Out, V> >(resT.State, () => { var resU = bind(resT.Value)(); if (resU.IsBottom) { return new WriterResult <Out, V>(default(V), resU.Output, true); } return WriterResult.Return(project(resT.Value, resU.Value), resU.Output); }); }); }
public static Writer <Out, State <S, V> > SelectMany <Out, S, T, U, V>( this Writer <Out, T> self, Func <T, State <S, U> > bind, Func <T, U, V> project ) { if (bind == null) { throw new ArgumentNullException("bind"); } if (project == null) { throw new ArgumentNullException("project"); } return(() => { var resT = self(); if (resT.IsBottom) { return WriterResult.Bottom <Out, State <S, V> >(resT.Output); } return WriterResult.Return <Out, State <S, V> >(state => { var resU = bind(resT.Value)(state); if (resU.IsBottom) { return StateResult.Bottom <S, V>(state); } return StateResult.Return(resU.State, project(resT.Value, resU.Value)); }, resT.Output); }); }
/// <summary> /// Creates a new State computation that is primed with the data of a particular /// failure event. /// </summary> /// <param name="strategy">Strategy as a State computation</param> /// <param name="pid">Process ID that failed</param> /// <param name="sender">Process that sent the message that cause the failure</param> /// <param name="parent">Supervisor of the failed Process</param> /// <param name="siblings">The siblings of the failed Process</param> /// <param name="ex">Exception</param> /// <param name="msg">Message that caused the failure</param> /// <returns>State computation that can be invoked by passing it /// an object of StrategyState. This will result in a StateResult that contains /// the mutated StrategyState and a StrategyDecision. The StrategyDecision /// contains all the information needed to decide the fate of a Process (and /// related processes)</returns> public static State <StrategyState, StrategyDecision> Failure( this State <StrategyContext, Unit> strategy, ProcessId pid, ProcessId sender, ProcessId parent, IEnumerable <ProcessId> siblings, Exception ex, object msg ) { return(stateInst => { var now = DateTime.UtcNow; var state = strategy(StrategyContext.Empty.With( Global: stateInst.With(Failures: stateInst.Failures + 1), FailedProcess: pid, ParentProcess: parent, Sender: sender, Siblings: siblings, Exception: ex, Message: msg)).State; var decision = new StrategyDecision( state.Directive.IfNone(Directive.Restart), state.MessageDirective.IfNone(MessageDirective.ForwardToDeadLetters), state.Affects, state.Pause ); return StateResult.Return(state.Global.With(LastFailure: now), decision); }); }
/// <summary> /// Select Many /// </summary> public static Reader <E, State <S, V> > SelectMany <E, S, T, U, V>( this Reader <E, T> self, Func <T, State <S, U> > bind, Func <T, U, V> project ) { if (bind == null) { throw new ArgumentNullException("bind"); } if (project == null) { throw new ArgumentNullException("project"); } return((E env) => { var resT = self(env); if (resT.IsBottom) { return Bottom <State <S, V> >(); } return Return <State <S, V> >(state => { var resU = bind(resT.Value)(state); if (resU.IsBottom) { return StateResult.Bottom <S, V>(state); } return StateResult.Return(resU.State, project(resT.Value, resU.Value)); }); }); }
public static State <S, V> SelectMany <S, T, U, V>( this State <S, T> self, Func <T, State <S, U> > bind, Func <T, U, V> project ) { if (bind == null) { throw new ArgumentNullException("bind"); } if (project == null) { throw new ArgumentNullException("project"); } return((S state) => { var resT = self(state); if (resT.IsBottom) { StateResult.Bottom <S, V>(state); } var resU = bind(resT.Value)(resT.State); if (resU.IsBottom) { StateResult.Bottom <S, V>(resT.State); } var resV = project(resT.Value, resU.Value); return StateResult.Return(resU.State, resV); }); }
public static State <S, int> Count <S, T>(this State <S, T> self) => s => { var res = self(s); return(res.IsBottom ? StateResult.Bottom <S, int>(s) : StateResult.Return(res.State, 1)); };
public static State <S, T> Where <S, T>(this State <S, T> self, Func <T, bool> pred) { return(state => { var res = self(state); return pred(res.Value) ? StateResult.Return(res.State, res.Value) : StateResult.Bottom <S, T>(state); }); }
public static State <S, Writer <Out, V> > FoldT <S, Out, T, V>(this State <S, Writer <Out, T> > self, V state, Func <V, T, V> fold) { return((S s) => { var inner = self(s); if (inner.IsBottom) { return StateResult.Bottom <S, Writer <Out, V> >(s); } return StateResult.Return(inner.State, inner.Value.Fold(state, fold)); }); }
public static State <S, R> Bind <S, T, R>(this State <S, T> self, Func <T, State <S, R> > binder) { return(state => { var resT = self(state); if (resT.IsBottom) { return StateResult.Bottom <S, R>(state); } return binder(resT.Value)(resT.State); }); }
private static StateResult <S, Unit> bmap <S, T>(StateResult <S, T> r, Action <T> f) { if (r.IsBottom) { return(StateResult.Bottom <S, Unit>(r.State)); } else { f(r.Value); return(StateResult.Return(r.State, unit)); } }
public static State <S, U> Select <S, T, U>(this State <S, T> self, Func <T, U> map) { if (map == null) { throw new ArgumentNullException("map"); } return((S state) => { var resT = self(state); return resT.IsBottom ? StateResult.Bottom <S, U>(state) : StateResult.Return(resT.State, map(resT.Value)); }); }
public static State <S, T> Modify <S, T>(this State <S, T> self, Func <S, S> f) { if (f == null) { throw new ArgumentNullException(nameof(map)); } return((S state) => { var resT = self(state); return resT.IsBottom ? StateResult.Bottom <S, T>(state) : StateResult.Return(f(resT.State), resT.Value); }); }
public static State <S, Option <T> > choose <S, T>(params State <S, Option <T> >[] monads) { return(state => { foreach (var monad in monads) { var res = monad(state); if (!res.IsBottom && res.Value.IsSome) { return res; } } return StateResult.Return <S, Option <T> >(state, None); }); }
public static State <S, T> LiftUnsafeT <Env, S, T>(this Reader <Env, State <S, T> > self, Env env) where T : class { return(state => { var inner = self(env); if (inner.IsBottom) { return StateResult.Bottom <S, T>(state); } var res = inner.Value(state); if (res.IsBottom) { return StateResult.Bottom <S, T>(state); } return StateResult.Return(res.State, res.Value); }); }
/// <summary> /// Compose a sequence of state computations /// </summary> public static State <StrategyContext, Unit> Compose(params State <StrategyContext, Unit>[] stages) => state => StateResult.Return(stages.Fold(state, (s, c) => c(s).State), unit);
/// <summary> /// Match a range of State computations that take the Exception that caused /// the failure and map it to an Optional Directive. The first computation to /// return a Some(Directive) will succeed /// </summary> /// <param name="directives">Directive maps</param> /// <returns>Strategy computation as a State monad</returns> public static State <StrategyContext, Unit> Match(params State <Exception, Option <Directive> >[] directives) => state => StateResult.Return( state.With( Directive: choose(directives.Concat(ProcessSetting.StandardDirectives) .ToArray())(state.Exception).Value), unit);
/// <summary> /// Match a range of State computations that take the currently selected /// Directive and map it to an Optional MessageDirective. The first computation /// to return a Some(MessageDirective) will succeed. If a Directive hasn't been /// chosen by the time this is invoked then RestartNow is used by default. /// </summary> /// <param name="directives">Directive maps</param> /// <returns>Strategy computation as a State monad</returns> public static State <StrategyContext, Unit> Redirect(params State <Directive, Option <MessageDirective> >[] directives) => state => StateResult.Return( state.With(MessageDirective: choose(directives)(state.Directive.IfNone(Directive.Restart)).Value), unit );
private static StateResult <S, R> bmap <S, T, R>(StateResult <S, T> r, Func <T, R> f) => r.IsBottom ? StateResult.Bottom <S, R>(r.State) : StateResult.Return(r.State, f(r.Value));